You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mp...@apache.org on 2016/06/02 16:18:25 UTC

[4/5] ambari git commit: AMBARI-17010. Scheduled requests should be executed using issuer role. (mpapirkovskyy)

AMBARI-17010. Scheduled requests should be executed using issuer role. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5d9348ce
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5d9348ce
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5d9348ce

Branch: refs/heads/branch-2.4
Commit: 5d9348cedc2a4b798811877d4652e9a3e9dd70a6
Parents: a52b57c
Author: Myroslav Papirkovskyi <mp...@hortonworks.com>
Authored: Thu Jun 2 18:33:50 2016 +0300
Committer: Myroslav Papirkovskyi <mp...@hortonworks.com>
Committed: Thu Jun 2 19:16:21 2016 +0300

----------------------------------------------------------------------
 .../controller/AmbariManagementController.java  |   7 +
 .../AmbariManagementControllerImpl.java         |   5 +
 .../ambari/server/controller/AmbariServer.java  |   9 +-
 .../controller/RequestScheduleResponse.java     |  13 +-
 .../RequestScheduleResourceProvider.java        |  11 +-
 .../orm/entities/RequestScheduleEntity.java     |  11 +
 .../scheduler/ExecutionScheduleManager.java     |   8 +-
 .../AmbariLocalUserDetailsService.java          |  99 ---------
 .../authorization/AmbariLocalUserProvider.java  | 113 ++++++++++
 .../authorization/AmbariUserAuthentication.java |  71 ++++++
 .../AmbariUserAuthorizationFilter.java          |  98 +++++++++
 .../authorization/AuthorizationHelper.java      |  20 ++
 .../server/security/authorization/Users.java    |   5 +
 .../state/scheduler/RequestExecution.java       |  10 +
 .../state/scheduler/RequestExecutionImpl.java   |  14 +-
 .../server/upgrade/UpgradeCatalog240.java       |   8 +
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |   1 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   1 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   1 +
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   1 +
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   1 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   1 +
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   1 +
 .../webapp/WEB-INF/spring-security.xml          |   5 +-
 .../RequestScheduleResourceProviderTest.java    |   2 +
 .../scheduler/ExecutionScheduleManagerTest.java |   4 +-
 ...ariAuthorizationProviderDisableUserTest.java |  25 ++-
 .../AmbariLocalUserDetailsServiceTest.java      |  74 -------
 .../AmbariLocalUserProviderTest.java            | 159 ++++++++++++++
 .../AmbariUserAuthenticationFilterTest.java     | 217 +++++++++++++++++++
 .../authorization/AuthorizationHelperTest.java  |  27 +++
 .../security/authorization/TestUsers.java       |  18 ++
 .../server/upgrade/UpgradeCatalog240Test.java   |  13 +-
 33 files changed, 853 insertions(+), 200 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index 10a1f8c..9f221d5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -549,6 +549,13 @@ public interface AmbariManagementController {
   String getAuthName();
 
   /**
+   * Get the authenticated user's id.
+   *
+   * @return the authenticated user's name
+   */
+  int getAuthId();
+
+  /**
    * Create and persist the request stages and return a response containing the
    * associated request and resulting tasks.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 411b494..fe9204d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -4327,6 +4327,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
   }
 
   @Override
+  public int getAuthId() {
+    return AuthorizationHelper.getAuthenticatedId();
+  }
+
+  @Override
   public Set<RootServiceResponse> getRootServices(
       Set<RootServiceRequest> requests) throws AmbariException {
     Set<RootServiceResponse> response = new HashSet<RootServiceResponse>();

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index cdc8185..961b6fe 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -99,8 +99,9 @@ import org.apache.ambari.server.security.CertificateManager;
 import org.apache.ambari.server.security.SecurityFilter;
 import org.apache.ambari.server.security.authentication.AmbariAuthenticationFilter;
 import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
+import org.apache.ambari.server.security.authorization.AmbariLocalUserProvider;
+import org.apache.ambari.server.security.authorization.AmbariUserAuthorizationFilter;
 import org.apache.ambari.server.security.authorization.AmbariLdapAuthenticationProvider;
-import org.apache.ambari.server.security.authorization.AmbariLocalUserDetailsService;
 import org.apache.ambari.server.security.authorization.PermissionHelper;
 import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.authorization.internal.AmbariInternalAuthenticationProvider;
@@ -319,14 +320,16 @@ public class AmbariServer {
         injector.getInstance(AuditLogger.class));
       factory.registerSingleton("permissionHelper",
         injector.getInstance(PermissionHelper.class));
-      factory.registerSingleton("ambariLocalUserService",
-        injector.getInstance(AmbariLocalUserDetailsService.class));
       factory.registerSingleton("ambariLdapAuthenticationProvider",
         injector.getInstance(AmbariLdapAuthenticationProvider.class));
+      factory.registerSingleton("ambariLocalAuthenticationProvider",
+        injector.getInstance(AmbariLocalUserProvider.class));
       factory.registerSingleton("ambariLdapDataPopulator",
         injector.getInstance(AmbariLdapDataPopulator.class));
       factory.registerSingleton("ambariAuthorizationFilter",
         injector.getInstance(AmbariAuthorizationFilter.class));
+      factory.registerSingleton("ambariUserAuthorizationFilter",
+        injector.getInstance(AmbariUserAuthorizationFilter.class));
       factory.registerSingleton("ambariInternalAuthenticationProvider",
         injector.getInstance(AmbariInternalAuthenticationProvider.class));
       factory.registerSingleton("ambariJwtAuthenticationFilter",

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestScheduleResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestScheduleResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestScheduleResponse.java
index 17f69c9..5516d46 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestScheduleResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/RequestScheduleResponse.java
@@ -33,13 +33,15 @@ public class RequestScheduleResponse {
   private String createTime;
   private String updateUser;
   private String updateTime;
+  private Integer authenticatedUserId;
 
   public RequestScheduleResponse(Long id, String clusterName,
                                  String description, String status,
                                  String lastExecutionStatus,
                                  Batch batch, Schedule schedule,
                                  String createUser, String createTime,
-                                 String updateUser, String updateTime) {
+                                 String updateUser, String updateTime,
+                                 Integer authenticatedUserId) {
     this.id = id;
     this.clusterName = clusterName;
     this.description = description;
@@ -51,6 +53,7 @@ public class RequestScheduleResponse {
     this.createTime = createTime;
     this.updateUser = updateUser;
     this.updateTime = updateTime;
+    this.authenticatedUserId = authenticatedUserId;
   }
 
   public Long getId() {
@@ -140,4 +143,12 @@ public class RequestScheduleResponse {
   public void setLastExecutionStatus(String lastExecutionStatus) {
     this.lastExecutionStatus = lastExecutionStatus;
   }
+
+  public Integer getAuthenticatedUserId() {
+    return authenticatedUserId;
+  }
+
+  public void setAuthenticatedUserId(Integer authenticatedUserId) {
+    this.authenticatedUserId = authenticatedUserId;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProvider.java
index e21193d..ce9168b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProvider.java
@@ -73,6 +73,8 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
     PropertyHelper.getPropertyId("RequestSchedule", "schedule");
   protected static final String REQUEST_SCHEDULE_CREATE_USER_PROPERTY_ID =
     PropertyHelper.getPropertyId("RequestSchedule", "create_user");
+  protected static final String REQUEST_SCHEDULE_AUTHENTICATED_USER_PROPERTY_ID =
+    PropertyHelper.getPropertyId("RequestSchedule", "authenticated_user");
   protected static final String REQUEST_SCHEDULE_UPDATE_USER_PROPERTY_ID =
     PropertyHelper.getPropertyId("RequestSchedule", "update_user");
   protected static final String REQUEST_SCHEDULE_CREATE_TIME_PROPERTY_ID =
@@ -207,6 +209,8 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
         response.getSchedule(), requestedIds);
       setResourceProperty(resource, REQUEST_SCHEDULE_CREATE_USER_PROPERTY_ID,
         response.getCreateUser(), requestedIds);
+      setResourceProperty(resource, REQUEST_SCHEDULE_AUTHENTICATED_USER_PROPERTY_ID,
+        response.getAuthenticatedUserId(), requestedIds);
       setResourceProperty(resource, REQUEST_SCHEDULE_CREATE_TIME_PROPERTY_ID,
         response.getCreateTime(), requestedIds);
       setResourceProperty(resource, REQUEST_SCHEDULE_UPDATE_USER_PROPERTY_ID,
@@ -365,6 +369,7 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
       }
 
       String username = getManagementController().getAuthName();
+      Integer userId = getManagementController().getAuthId();
 
       requestExecution.setBatch(request.getBatch());
       requestExecution.setDescription(request.getDescription());
@@ -374,6 +379,7 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
         requestExecution.setStatus(RequestExecution.Status.valueOf(request.getStatus()));
       }
       requestExecution.setUpdateUser(username);
+      requestExecution.setAuthenticatedUserId(userId);
 
       LOG.info("Persisting updated Request Schedule "
         + ", clusterName = " + request.getClusterName()
@@ -417,12 +423,14 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
       }
 
       String username = getManagementController().getAuthName();
+      Integer userId = getManagementController().getAuthId();
 
       RequestExecution requestExecution = requestExecutionFactory.createNew
         (cluster, request.getBatch(), request.getSchedule());
 
       requestExecution.setCreateUser(username);
       requestExecution.setUpdateUser(username);
+      requestExecution.setAuthenticatedUserId(userId);
       requestExecution.setStatus(RequestExecution.Status.SCHEDULED);
 
       LOG.info("Persisting new Request Schedule "
@@ -443,7 +451,8 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
           requestExecution.getLastExecutionStatus(),
           requestExecution.getBatch(), request.getSchedule(),
           requestExecution.getCreateUser(), requestExecution.getCreateTime(),
-          requestExecution.getUpdateUser(), requestExecution.getUpdateTime());
+          requestExecution.getUpdateUser(), requestExecution.getUpdateTime(),
+          requestExecution.getAuthenticatedUserId());
 
       responses.add(response);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleEntity.java
index fa7094e..b1bc20a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleEntity.java
@@ -69,6 +69,9 @@ public class RequestScheduleEntity {
   @Column(name = "batch_toleration_limit")
   private Integer batchTolerationLimit;
 
+  @Column(name = "authenticated_user_id")
+  private Integer authenticatedUserId;
+
   @Column(name = "create_user")
   private String createUser;
 
@@ -296,6 +299,14 @@ public class RequestScheduleEntity {
     this.requestEntities = requestEntities;
   }
 
+  public Integer getAuthenticatedUserId() {
+    return authenticatedUserId;
+  }
+
+  public void setAuthenticatedUserId(Integer authenticatedUser) {
+    this.authenticatedUserId = authenticatedUser;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
index 2472fe0..dbce272 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
@@ -96,6 +96,8 @@ public class ExecutionScheduleManager {
     "RequestExecution";
   protected static final String DEFAULT_API_PATH = "api/v1";
 
+  public static final String USER_ID_HEADER = "X-Authenticated-User-ID";
+
   protected Client ambariClient;
   protected WebResource ambariWebResource;
 
@@ -521,7 +523,7 @@ public class ExecutionScheduleManager {
 
       body = requestExecution.getRequestBody(batchId);
 
-      BatchRequestResponse batchRequestResponse = performApiRequest(uri, body, type);
+      BatchRequestResponse batchRequestResponse = performApiRequest(uri, body, type, requestExecution.getAuthenticatedUserId());
 
       updateBatchRequest(executionId, batchId, clusterName, batchRequestResponse, false);
 
@@ -668,10 +670,10 @@ public class ExecutionScheduleManager {
     return convertToBatchRequestResponse(response);
   }
 
-  protected BatchRequestResponse performApiRequest(String relativeUri, String body, String method) {
+  protected BatchRequestResponse performApiRequest(String relativeUri, String body, String method, Integer userId) {
     ClientResponse response;
     try {
-      response = ambariWebResource.path(relativeUri).method(method, ClientResponse.class, body);
+      response = ambariWebResource.path(relativeUri).header(USER_ID_HEADER, userId).method(method, ClientResponse.class, body);
     } catch (UniformInterfaceException e) {
       response = e.getResponse();
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsService.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsService.java
deleted file mode 100644
index 5607cc5..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsService.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * 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.security.authorization;
-
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.orm.dao.MemberDAO;
-import org.apache.ambari.server.orm.dao.PrivilegeDAO;
-import org.apache.ambari.server.orm.dao.UserDAO;
-import org.apache.ambari.server.orm.entities.MemberEntity;
-import org.apache.ambari.server.orm.entities.PrincipalEntity;
-import org.apache.ambari.server.orm.entities.PrivilegeEntity;
-import org.apache.ambari.server.orm.entities.UserEntity;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-
-import java.util.LinkedList;
-import java.util.List;
-
-
-public class AmbariLocalUserDetailsService implements UserDetailsService {
-  private static final Logger log = LoggerFactory.getLogger(AmbariLocalUserDetailsService.class);
-
-  Injector injector;
-  Configuration configuration;
-  private AuthorizationHelper authorizationHelper;
-  UserDAO userDAO;
-  MemberDAO memberDAO;
-  PrivilegeDAO privilegeDAO;
-
-  @Inject
-  public AmbariLocalUserDetailsService(Injector injector, Configuration configuration,
-                                       AuthorizationHelper authorizationHelper, UserDAO userDAO,
-                                       MemberDAO memberDAO, PrivilegeDAO privilegeDAO) {
-    this.injector = injector;
-    this.configuration = configuration;
-    this.authorizationHelper = authorizationHelper;
-    this.userDAO = userDAO;
-    this.memberDAO = memberDAO;
-    this.privilegeDAO = privilegeDAO;
-  }
-
-  /**
-   * Loads Spring Security UserDetails from identity storage according to Configuration
-   *
-   * @param username username
-   * @return UserDetails
-   * @throws UsernameNotFoundException when user not found or have empty roles
-   */
-  @Override
-  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-    log.info("Loading user by name: " + username);
-
-    UserEntity user = userDAO.findLocalUserByName(username);
-
-    if (user == null || !StringUtils.equals(user.getUserName(), username)) {
-      //TODO case insensitive name comparison is a temporary solution, until users API will change to use id as PK
-      log.info("user not found ");
-      throw new UsernameNotFoundException("Username " + username + " not found");
-    }
-
-    // get all of the privileges for the user
-    List<PrincipalEntity> principalEntities = new LinkedList<PrincipalEntity>();
-
-    principalEntities.add(user.getPrincipal());
-
-    List<MemberEntity> memberEntities = memberDAO.findAllMembersByUser(user);
-
-    for (MemberEntity memberEntity : memberEntities) {
-      principalEntities.add(memberEntity.getGroup().getPrincipal());
-    }
-
-    List<PrivilegeEntity> privilegeEntities = privilegeDAO.findAllByPrincipal(principalEntities);
-
-    return new User(user.getUserName(), user.getUserPassword(), user.getActive(), 
-        true, true, true, authorizationHelper.convertPrivilegesToAuthorities(privilegeEntities));
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
new file mode 100644
index 0000000..a8c9b19
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
@@ -0,0 +1,113 @@
+/**
+ * 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.security.authorization;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.DisabledException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+import java.util.Collection;
+
+public class AmbariLocalUserProvider extends AbstractUserDetailsAuthenticationProvider {
+  private static final Logger LOG = LoggerFactory.getLogger(AmbariLocalUserProvider.class);
+
+  private UserDAO userDAO;
+  private Users users;
+  private PasswordEncoder passwordEncoder;
+
+
+  @Inject
+  public AmbariLocalUserProvider(UserDAO userDAO, Users users, PasswordEncoder passwordEncoder) {
+    this.userDAO = userDAO;
+    this.users = users;
+    this.passwordEncoder = passwordEncoder;
+  }
+
+  @Override
+  protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
+    // do nothing
+  }
+
+  @Override
+  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+    String userName = authentication.getName().trim();
+
+    LOG.info("Loading user by name: " + userName);
+
+    UserEntity userEntity = userDAO.findLocalUserByName(userName);
+
+    if (userEntity == null || !StringUtils.equals(userEntity.getUserName(), userName)) {
+      //TODO case insensitive name comparison is a temporary solution, until users API will change to use id as PK
+      LOG.info("user not found ");
+      throw new UsernameNotFoundException("Username " + userName + " not found");
+    }
+
+    if (!userEntity.getActive()) {
+      logger.debug("User account is disabled");
+
+      throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled",
+        "User is disabled"));
+    }
+
+    if (authentication.getCredentials() == null) {
+      logger.debug("Authentication failed: no credentials provided");
+
+      throw new BadCredentialsException(messages.getMessage(
+        "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
+    }
+
+    String password = userEntity.getUserPassword();
+    String presentedPassword = authentication.getCredentials().toString();
+
+    if (!passwordEncoder.matches(presentedPassword, password)) {
+      logger.debug("Authentication failed: password does not match stored value");
+
+      throw new BadCredentialsException(messages.getMessage(
+        "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
+    }
+    Collection<AmbariGrantedAuthority> userAuthorities =
+      users.getUserAuthorities(userEntity.getUserName(), userEntity.getUserType());
+
+    User user = new User(userEntity);
+    Authentication auth = new AmbariUserAuthentication(userEntity.getUserPassword(), user, userAuthorities);
+    auth.setAuthenticated(true);
+    return auth;
+  }
+
+  @Override
+  protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
+    return null;
+  }
+
+  @Override
+  public boolean supports(Class<?> authentication) {
+    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthentication.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthentication.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthentication.java
new file mode 100644
index 0000000..f9c5cf4
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthentication.java
@@ -0,0 +1,71 @@
+/**
+ * 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.security.authorization;
+
+import org.springframework.security.core.Authentication;
+
+import java.util.Collection;
+
+public class AmbariUserAuthentication implements Authentication {
+
+  private String serializedToken;
+  private User user;
+  private Collection<AmbariGrantedAuthority> userAuthorities;
+  private boolean authenticated = false;
+
+  public AmbariUserAuthentication(String token, User user, Collection<AmbariGrantedAuthority> userAuthorities) {
+    this.serializedToken = token;
+    this.user = user;
+    this.userAuthorities = userAuthorities;
+  }
+
+  @Override
+  public Collection<? extends AmbariGrantedAuthority> getAuthorities() {
+    return userAuthorities;
+  }
+
+  @Override
+  public String getCredentials() {
+    return serializedToken;
+  }
+
+  @Override
+  public Object getDetails() {
+    return null;
+  }
+
+  @Override
+  public User getPrincipal() {
+    return user;
+  }
+
+  @Override
+  public boolean isAuthenticated() {
+    return authenticated;
+  }
+
+  @Override
+  public void setAuthenticated(boolean authenticated) throws IllegalArgumentException {
+    this.authenticated = authenticated;
+  }
+
+  @Override
+  public String getName() {
+    return user.getUserName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
new file mode 100644
index 0000000..b7a1610
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
@@ -0,0 +1,98 @@
+/**
+ * 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.security.authorization;
+
+import com.google.inject.Inject;
+import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenClientFilter;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenStorage;
+import org.apache.commons.lang.math.NumberUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collection;
+
+public class AmbariUserAuthorizationFilter implements Filter {
+
+  private final InternalTokenStorage internalTokenStorage;
+  private final Users users;
+
+  @Inject
+  public AmbariUserAuthorizationFilter(InternalTokenStorage internalTokenStorage, Users users) {
+    this.internalTokenStorage = internalTokenStorage;
+    this.users = users;
+  }
+
+  @Override
+  public void init(FilterConfig filterConfig) throws ServletException {
+    // do nothing
+  }
+
+  @Override
+  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+    HttpServletRequest httpRequest = (HttpServletRequest) request;
+    HttpServletResponse httpResponse = (HttpServletResponse) response;
+
+    String token = httpRequest.getHeader(InternalTokenClientFilter.INTERNAL_TOKEN_HEADER);
+    if (token != null) {
+      if (internalTokenStorage.isValidInternalToken(token)) {
+        String userToken = httpRequest.getHeader(ExecutionScheduleManager.USER_ID_HEADER);
+        if (userToken != null) {
+          if (!NumberUtils.isDigits(userToken)) {
+            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid user ID");
+            httpResponse.flushBuffer();
+            return;
+          }
+          Integer userId = Integer.parseInt(userToken);
+          User user = users.getUser(userId);
+          if (user == null) {
+            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Authentication required");
+            httpResponse.flushBuffer();
+            return;
+          } if (!user.isActive()) {
+            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not active");
+            httpResponse.flushBuffer();
+            return;
+          } else {
+            Collection<AmbariGrantedAuthority> userAuthorities =
+              users.getUserAuthorities(user.getUserName(), user.getUserType());
+            AmbariUserAuthentication authentication = new AmbariUserAuthentication(token, user, userAuthorities);
+            authentication.setAuthenticated(true);
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+            httpResponse.setHeader("User", AuthorizationHelper.getAuthenticatedName());
+          }
+        }
+      }
+    }
+    chain.doFilter(request, response);
+  }
+
+  @Override
+  public void destroy() {
+    // do nothing
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
index f9f0611..8befc3f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
@@ -98,6 +98,26 @@ public class AuthorizationHelper {
   }
 
   /**
+   * Gets the ID of the logged-in user.  Thread-safe due to use of
+   * thread-local.
+   *
+   * @return the ID of the logged-in user
+   */
+  public static int getAuthenticatedId() {
+    SecurityContext securityContext = SecurityContextHolder.getContext();
+
+    Authentication authentication = securityContext.getAuthentication();
+    AmbariUserAuthentication auth;
+    if (authentication instanceof AmbariUserAuthentication) {
+      auth = (AmbariUserAuthentication) authentication;
+    } else {
+      return -1;
+    }
+
+    return auth.getPrincipal().getUserId();
+  }
+
+  /**
    * Determines if the authenticated user (from application's security context) is authorized to
    * perform an operation on the specific resource by matching the authenticated user's
    * authorizations with the one indicated.

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
index d80edf3..545095d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
@@ -119,6 +119,11 @@ public class Users {
     return (null == userEntity) ? null : new User(userEntity);
   }
 
+  public User getUser(Integer userId) {
+    UserEntity userEntity = userDAO.findByPK(userId);
+    return (null == userEntity) ? null : new User(userEntity);
+  }
+
   /**
    * Modifies password of local user
    * @throws AmbariException

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
index 06a46c7..8a325f4 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
@@ -105,6 +105,11 @@ public interface RequestExecution {
   public void setLastExecutionStatus(String status);
 
   /**
+   * Set authenticated user
+   */
+  public void setAuthenticatedUserId(Integer username);
+
+  /**
    * Set create username
    */
   public void setCreateUser(String username);
@@ -125,6 +130,11 @@ public interface RequestExecution {
   public String getUpdateTime();
 
   /**
+   * Get authenticated user
+   */
+  public Integer getAuthenticatedUserId();
+
+  /**
    * Get create user
    */
   public String getCreateUser();

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
index 895579e..8c952a7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
@@ -30,7 +30,6 @@ import org.apache.ambari.server.orm.dao.RequestScheduleBatchRequestDAO;
 import org.apache.ambari.server.orm.dao.RequestScheduleDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntity;
-import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntityPK;
 import org.apache.ambari.server.orm.entities.RequestScheduleEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -174,7 +173,8 @@ public class RequestExecutionImpl implements RequestExecution {
         requestScheduleEntity.getCreateUser(),
         DateUtils.convertToReadableTime(requestScheduleEntity.getCreateTimestamp()),
         requestScheduleEntity.getUpdateUser(),
-        DateUtils.convertToReadableTime(requestScheduleEntity.getUpdateTimestamp())
+        DateUtils.convertToReadableTime(requestScheduleEntity.getUpdateTimestamp()),
+        requestScheduleEntity.getAuthenticatedUserId()
       );
       return response;
     } finally {
@@ -340,6 +340,11 @@ public class RequestExecutionImpl implements RequestExecution {
   }
 
   @Override
+  public void setAuthenticatedUserId(Integer username) {
+    requestScheduleEntity.setAuthenticatedUserId(username);
+  }
+
+  @Override
   public void setCreateUser(String username) {
     requestScheduleEntity.setCreateUser(username);
   }
@@ -362,6 +367,11 @@ public class RequestExecutionImpl implements RequestExecution {
   }
 
   @Override
+  public Integer getAuthenticatedUserId() {
+    return requestScheduleEntity.getAuthenticatedUserId();
+  }
+
+  @Override
   public String getCreateUser() {
     return requestScheduleEntity.getCreateUser();
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
index 19d370c..1653c95 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
@@ -154,6 +154,8 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
   public static final String VIEWINSTANCE_TABLE = "viewinstance";
   public static final String SHORT_URL_COLUMN = "short_url";
   public static final String CLUSTER_HANDLE_COLUMN = "cluster_handle";
+  public static final String REQUESTSCHEDULE_TABLE = "requestschedule";
+  public static final String AUTHENTICATED_USER_ID_COLUMN = "authenticated_user_id";
   protected static final String CLUSTER_VERSION_TABLE = "cluster_version";
   protected static final String HOST_VERSION_TABLE = "host_version";
   protected static final String PHOENIX_QUERY_SERVER_PRINCIPAL_KEY = "phoenix.queryserver.kerberos.principal";
@@ -275,6 +277,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
     updateViewInstanceEntityTable();
     createRemoteClusterTable();
     updateViewInstanceTable();
+    updateRequestScheduleEntityTable();
   }
 
   private void createRemoteClusterTable() throws SQLException {
@@ -324,6 +327,11 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
       new DBColumnInfo(CLUSTER_TYPE_COLUMN, String.class, 100, ClusterType.LOCAL_AMBARI.name(), false));
   }
 
+  private void updateRequestScheduleEntityTable() throws SQLException {
+    dbAccessor.addColumn(REQUESTSCHEDULE_TABLE,
+      new DBColumnInfo(AUTHENTICATED_USER_ID_COLUMN, Integer.class, null, null, true));
+  }
+
   private void updateClusterTableDDL() throws SQLException {
     dbAccessor.addColumn(CLUSTER_TABLE, new DBColumnInfo(CLUSTER_UPGRADE_ID_COLUMN, Long.class, null, null, true));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index 175fd59..940542d 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -296,6 +296,7 @@ CREATE TABLE requestschedule (
   status varchar(255),
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_timestamp bigint,
   update_user varchar(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index ffc47fa..eb2b349 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -296,6 +296,7 @@ CREATE TABLE requestschedule (
   status varchar(255),
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_timestamp bigint,
   update_user varchar(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index e646ac5..de8c2e6 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -287,6 +287,7 @@ CREATE TABLE requestschedule (
   status VARCHAR2(255),
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id NUMBER(10),
   create_user VARCHAR2(255),
   create_timestamp NUMBER(19),
   update_user VARCHAR2(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index c5734a7..0a8d6c9 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -296,6 +296,7 @@ CREATE TABLE requestschedule (
   status varchar(255),
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_timestamp bigint,
   update_user varchar(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index 4b3c6e7..4b65a69 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -356,6 +356,7 @@ CREATE TABLE ambari.requestschedule (
   status varchar(255),
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_timestamp bigint,
   update_user varchar(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index 74e85ef..5ef07d0 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -285,6 +285,7 @@ CREATE TABLE requestschedule (
   status VARCHAR(255),
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user VARCHAR(255),
   create_timestamp NUMERIC(19),
   update_user VARCHAR(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index bd33290..0b5f3b8 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -301,6 +301,7 @@ CREATE TABLE requestschedule (
   STATUS VARCHAR(255),
   batch_separation_seconds SMALLINT,
   batch_toleration_limit SMALLINT,
+  authenticated_user_id INTEGER,
   create_user VARCHAR(255),
   create_timestamp BIGINT,
   update_user VARCHAR(255),

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml b/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
index 01243ef..e1697e2 100644
--- a/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
+++ b/ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
@@ -25,6 +25,7 @@
   <http use-expressions="true"
         disable-url-rewriting="true" entry-point-ref="ambariEntryPoint">
     <intercept-url pattern="/**" access="isAuthenticated()"/>
+    <custom-filter ref="ambariUserAuthorizationFilter" before="BASIC_AUTH_FILTER"/>
     <custom-filter ref="ambariAuthenticationFilter" position="BASIC_AUTH_FILTER"/>
     <custom-filter ref="ambariJwtAuthenticationFilter" after="BASIC_AUTH_FILTER" />
     <custom-filter ref="ambariAuthorizationFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
@@ -34,9 +35,7 @@
 
   <authentication-manager alias="authenticationManager">
 
-    <authentication-provider user-service-ref="ambariLocalUserService">
-      <password-encoder ref="passwordEncoder"/>
-    </authentication-provider>
+    <authentication-provider ref="ambariLocalAuthenticationProvider"/>
 
     <authentication-provider ref="ambariLdapAuthenticationProvider"/>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProviderTest.java
index daeea27..51650c0 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProviderTest.java
@@ -88,6 +88,7 @@ public class RequestScheduleResourceProviderTest {
     expect(managementController.getRequestExecutionFactory()).andReturn
       (executionFactory);
     expect(managementController.getAuthName()).andReturn("admin").anyTimes();
+    expect(managementController.getAuthId()).andReturn(1).anyTimes();
 
     Capture<Cluster> clusterCapture = new Capture<Cluster>();
     Capture<Batch> batchCapture = new Capture<Batch>();
@@ -196,6 +197,7 @@ public class RequestScheduleResourceProviderTest {
     expect(managementController.getClusters()).andReturn(clusters).anyTimes();
     expect(clusters.getCluster("Cluster100")).andReturn(cluster).anyTimes();
     expect(managementController.getAuthName()).andReturn("admin").anyTimes();
+    expect(managementController.getAuthId()).andReturn(1).anyTimes();
     expect(managementController.getExecutionScheduleManager()).andReturn
       (executionScheduleManager).anyTimes();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
index 2f97eeb..860e647 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
@@ -356,6 +356,7 @@ public class ExecutionScheduleManagerTest {
     String uri = "clusters";
     String type = "post";
     String body = "body";
+    Integer userId = 1;
     Map<Long, RequestExecution> executionMap = new HashMap<Long, RequestExecution>();
     executionMap.put(executionId, requestExecutionMock);
 
@@ -378,11 +379,12 @@ public class ExecutionScheduleManagerTest {
 
     expect(requestExecutionMock.getBatchRequest(eq(batchId))).andReturn(batchRequestMock).once();
     expect(requestExecutionMock.getRequestBody(eq(batchId))).andReturn(body).once();
+    expect(requestExecutionMock.getAuthenticatedUserId()).andReturn(userId).once();
 
     expect(batchRequestMock.getUri()).andReturn(uri).once();
     expect(batchRequestMock.getType()).andReturn(type).once();
 
-    expect(scheduleManager.performApiRequest(eq(uri), eq(body), eq(type))).andReturn(batchRequestResponse).once();
+    expect(scheduleManager.performApiRequest(eq(uri), eq(body), eq(type), eq(userId))).andReturn(batchRequestResponse).once();
 
     scheduleManager.updateBatchRequest(eq(executionId), eq(batchId), eq(clusterName), eq(batchRequestResponse), eq(false));
     expectLastCall().once();

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationProviderDisableUserTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationProviderDisableUserTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationProviderDisableUserTest.java
index c3e5990..16cba8b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationProviderDisableUserTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationProviderDisableUserTest.java
@@ -21,6 +21,7 @@ package org.apache.ambari.server.security.authorization;
 import org.apache.ambari.server.orm.dao.MemberDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
 import org.junit.Assert;
 import org.junit.Before;
@@ -28,36 +29,35 @@ import org.junit.Test;
 import org.mockito.Mockito;
 import org.springframework.security.authentication.DisabledException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.StandardPasswordEncoder;
 
 public class AmbariAuthorizationProviderDisableUserTest {
 
+  private Users users;
+
   private UserDAO userDAO;
   
   private PasswordEncoder encoder = new StandardPasswordEncoder();
-  
-  private DaoAuthenticationProvider daoProvider;
+
+  private AmbariLocalUserProvider alup;
 
   private AmbariLdapAuthoritiesPopulator ldapPopulator;
 
   @Before
   public void setUp() {
     userDAO = Mockito.mock(UserDAO.class);
-    
+    users = Mockito.mock(Users.class);
+
     createUser("activeUser", true);
     createUser("disabledUser", false);
     
     MemberDAO memberDao = Mockito.mock(MemberDAO.class);
     PrivilegeDAO privilegeDao = Mockito.mock(PrivilegeDAO.class);
     AuthorizationHelper authorizationHelper = new AuthorizationHelper();
-    
-    AmbariLocalUserDetailsService uds = new AmbariLocalUserDetailsService(null,null,authorizationHelper,userDAO,memberDao,privilegeDao);
-    daoProvider = new DaoAuthenticationProvider();
-    daoProvider.setUserDetailsService(uds);
-    daoProvider.setPasswordEncoder(encoder);
+
+    alup = new AmbariLocalUserProvider(userDAO, users, encoder);
     
     ldapPopulator = new AmbariLdapAuthoritiesPopulator(authorizationHelper, userDAO, memberDao, privilegeDao);
     
@@ -65,13 +65,13 @@ public class AmbariAuthorizationProviderDisableUserTest {
   
   @Test public void testDisabledUserViaDaoProvider(){
     try{
-      daoProvider.authenticate(new UsernamePasswordAuthenticationToken("disabledUser","pwd"));
+      alup.authenticate(new UsernamePasswordAuthenticationToken("disabledUser","pwd"));
       Assert.fail("Disabled user passes authentication");
     }catch(DisabledException e){
       //expected
       Assert.assertEquals("User is disabled", e.getMessage());//UI depends on this
     }
-    Authentication auth = daoProvider.authenticate(new UsernamePasswordAuthenticationToken("activeUser","pwd"));
+    Authentication auth = alup.authenticate(new UsernamePasswordAuthenticationToken("activeUser","pwd"));
     Assert.assertNotNull(auth);
     Assert.assertTrue(auth.isAuthenticated());
   }
@@ -87,10 +87,13 @@ public class AmbariAuthorizationProviderDisableUserTest {
   }
   
   private void createUser(String login, boolean isActive) {
+    PrincipalEntity principalEntity = new PrincipalEntity();
     UserEntity activeUser = new UserEntity();
+    activeUser.setUserId(1);
     activeUser.setActive(isActive);
     activeUser.setUserName(login);
     activeUser.setUserPassword(encoder.encode("pwd"));
+    activeUser.setPrincipal(principalEntity);
     Mockito.when(userDAO.findLocalUserByName(login)).thenReturn(activeUser);
     Mockito.when(userDAO.findLdapUserByName(login)).thenReturn(activeUser);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java
deleted file mode 100644
index b77f4bc..0000000
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * 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.security.authorization;
-
-import com.google.inject.Guice;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-
-import org.apache.ambari.server.audit.AuditLoggerModule;
-import org.apache.ambari.server.orm.GuiceJpaInitializer;
-import org.apache.ambari.server.orm.OrmTestHelper;
-import org.apache.ambari.server.orm.dao.UserDAO;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.crypto.password.PasswordEncoder;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class AmbariLocalUserDetailsServiceTest {
-
-  private static Injector injector;
-
-  @Inject
-  AmbariLocalUserDetailsService userDetailsService;
-  @Inject
-  PasswordEncoder passwordEncoder;
-  @Inject
-  UserDAO userDAO;
-
-  @BeforeClass
-  public static void prepareData() {
-    injector = Guice.createInjector(new AuditLoggerModule(), new AuthorizationTestModule());
-    injector.getInstance(GuiceJpaInitializer.class);
-    injector.getInstance(OrmTestHelper.class).createTestUsers();
-  }
-
-  @Before
-  public void setUp() throws Exception {
-    injector.injectMembers(this);
-  }
-
-  @Test
-  public void testLoadUserByUsername() throws Exception {
-    UserDetails userDetails = userDetailsService.loadUserByUsername("administrator");
-    assertEquals("Wrong username", "administrator", userDetails.getUsername());
-    assertTrue("Password not matches", passwordEncoder.matches("admin", userDetails.getPassword()));
-    assertFalse("Wrong password accepted", passwordEncoder.matches("wrong", userDetails.getPassword()));
-  }
-
-  @Test(expected = UsernameNotFoundException.class)
-  public void testUsernameNotFound() throws Exception {
-    userDetailsService.loadUserByUsername("notExists_123123123");
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProviderTest.java
new file mode 100644
index 0000000..6dda3f2
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProviderTest.java
@@ -0,0 +1,159 @@
+/**
+ * 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.security.authorization;
+
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import org.apache.ambari.server.audit.AuditLoggerModule;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.OrmTestHelper;
+import org.apache.ambari.server.orm.dao.UserDAO;
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class AmbariLocalUserProviderTest {
+  private static Injector injector;
+
+  @Inject
+  PasswordEncoder passwordEncoder;
+
+  private static final String TEST_USER_NAME = "userName";
+  private static final String TEST_USER_PASS = "userPass";
+  private static final String TEST_USER_INCORRECT_PASS = "userIncorrectPass";
+
+  @BeforeClass
+  public static void prepareData() {
+    injector = Guice.createInjector(new AuditLoggerModule(), new AuthorizationTestModule());
+    injector.getInstance(GuiceJpaInitializer.class);
+    injector.getInstance(OrmTestHelper.class).createTestUsers();
+  }
+
+  @Before
+  public void setUp() throws Exception {
+    injector.injectMembers(this);
+    SecurityContextHolder.getContext().setAuthentication(null);
+  }
+
+  @Test
+  public void testSuccessfulAuth() {
+    Users users = createMock(Users.class);
+    UserDAO userDAO = createMock(UserDAO.class);
+    Authentication authentication = createMock(Authentication.class);
+
+    UserEntity userEntity = combineUserEntity();
+
+    expect(authentication.getName()).andReturn(TEST_USER_NAME);
+    expect(userDAO.findLocalUserByName(TEST_USER_NAME)).andReturn(userEntity);
+    expect(authentication.getCredentials()).andReturn(TEST_USER_PASS).anyTimes();
+    expect(users.getUserAuthorities(userEntity.getUserName(), userEntity.getUserType())).andReturn(null);
+
+    replay(users, userDAO, authentication);
+
+    AmbariLocalUserProvider ambariLocalUserProvider = new AmbariLocalUserProvider(userDAO, users, passwordEncoder);
+    Authentication resultedAuth = ambariLocalUserProvider.authenticate(authentication);
+
+    verify(users, userDAO, authentication);
+
+    assertNotNull(resultedAuth);
+    assertEquals(true, resultedAuth.isAuthenticated());
+    assertTrue(resultedAuth instanceof AmbariUserAuthentication);
+    assertEquals(1, ((User) resultedAuth.getPrincipal()).getUserId());
+  }
+
+  @Test(expected = UsernameNotFoundException.class)
+  public void testAuthWithIncorrectName() {
+    Users users = createMock(Users.class);
+    UserDAO userDAO = createMock(UserDAO.class);
+    Authentication authentication = createMock(Authentication.class);
+
+    expect(authentication.getName()).andReturn(TEST_USER_NAME);
+    expect(userDAO.findLocalUserByName(TEST_USER_NAME)).andReturn(null);
+
+    replay(users, userDAO, authentication);
+
+    AmbariLocalUserProvider ambariLocalUserProvider = new AmbariLocalUserProvider(userDAO, users, passwordEncoder);
+    ambariLocalUserProvider.authenticate(authentication);
+  }
+
+  @Test(expected = BadCredentialsException.class)
+  public void testAuthWithoutPass() {
+    Users users = createMock(Users.class);
+    UserDAO userDAO = createMock(UserDAO.class);
+    Authentication authentication = createMock(Authentication.class);
+
+    UserEntity userEntity = combineUserEntity();
+
+    expect(authentication.getName()).andReturn(TEST_USER_NAME);
+    expect(userDAO.findLocalUserByName(TEST_USER_NAME)).andReturn(userEntity);
+    expect(authentication.getCredentials()).andReturn(null);
+
+    replay(users, userDAO, authentication);
+
+    AmbariLocalUserProvider ambariLocalUserProvider = new AmbariLocalUserProvider(userDAO, users, passwordEncoder);
+    ambariLocalUserProvider.authenticate(authentication);
+  }
+
+  @Test(expected = BadCredentialsException.class)
+  public void testAuthWithIncorrectPass() {
+    Users users = createMock(Users.class);
+    UserDAO userDAO = createMock(UserDAO.class);
+    Authentication authentication = createMock(Authentication.class);
+
+    UserEntity userEntity = combineUserEntity();
+
+    expect(authentication.getName()).andReturn(TEST_USER_NAME);
+    expect(userDAO.findLocalUserByName(TEST_USER_NAME)).andReturn(userEntity);
+    expect(authentication.getCredentials()).andReturn(TEST_USER_INCORRECT_PASS).anyTimes();
+
+    replay(users, userDAO, authentication);
+
+    AmbariLocalUserProvider ambariLocalUserProvider = new AmbariLocalUserProvider(userDAO, users, passwordEncoder);
+    ambariLocalUserProvider.authenticate(authentication);
+  }
+
+
+
+  private UserEntity combineUserEntity() {
+    PrincipalEntity principalEntity = new PrincipalEntity();
+    UserEntity userEntity = new UserEntity();
+    userEntity.setUserId(1);
+    userEntity.setUserName(TEST_USER_NAME);
+    userEntity.setUserPassword(passwordEncoder.encode(TEST_USER_PASS));
+    userEntity.setUserType(UserType.LOCAL);
+    userEntity.setPrincipal(principalEntity);
+
+    return userEntity;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariUserAuthenticationFilterTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariUserAuthenticationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariUserAuthenticationFilterTest.java
new file mode 100644
index 0000000..b206078
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariUserAuthenticationFilterTest.java
@@ -0,0 +1,217 @@
+/**
+ * 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.security.authorization;
+
+import org.apache.ambari.server.orm.entities.PrincipalEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenClientFilter;
+import org.apache.ambari.server.security.authorization.internal.InternalTokenStorage;
+import org.easymock.Capture;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashSet;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.newCapture;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class AmbariUserAuthenticationFilterTest {
+  private static final String TEST_INTERNAL_TOKEN = "test token";
+  private static final String TEST_USER_ID_HEADER = "1";
+  private static final String TEST_USER_NAME = "userName";
+  private static final int TEST_USER_ID = 1;
+
+  @Before
+  public void setUp() throws Exception {
+    SecurityContextHolder.getContext().setAuthentication(null);
+  }
+
+  @Test
+  public void testDoFilterValid() throws IOException, ServletException {
+    final Users users = createMock(Users.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+    FilterChain chain = createMock(FilterChain.class);
+    InternalTokenStorage tokenStorage = createMock(InternalTokenStorage.class);
+
+    expect(request.getHeader(InternalTokenClientFilter.INTERNAL_TOKEN_HEADER)).andReturn(TEST_INTERNAL_TOKEN);
+    expect(tokenStorage.isValidInternalToken(TEST_INTERNAL_TOKEN)).andReturn(true);
+    expect(request.getHeader(ExecutionScheduleManager.USER_ID_HEADER)).andReturn(TEST_USER_ID_HEADER);
+
+    User user = combineUser();
+
+    expect(users.getUser(TEST_USER_ID)).andReturn(user);
+    expect(users.getUserAuthorities(user.getUserName(), user.getUserType())).andReturn(new HashSet<AmbariGrantedAuthority>());
+    Capture<String> userHeaderValue = newCapture();
+    response.setHeader(eq("User"), capture(userHeaderValue));
+    expectLastCall();
+
+    chain.doFilter(request, response);
+    expectLastCall();
+
+    replay(users, request, response, chain, tokenStorage);
+
+    AmbariUserAuthorizationFilter filter = new AmbariUserAuthorizationFilter(tokenStorage, users);
+    filter.doFilter(request, response, chain);
+
+    verify(users, request, response, chain, tokenStorage);
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+    assertNotNull(authentication);
+    assertEquals(true, authentication.isAuthenticated());
+    assertEquals(TEST_USER_NAME, userHeaderValue.getValue());
+  }
+
+  @Test
+  public void testDoFilterWithoutInternalToken() throws IOException, ServletException {
+    final Users users = createMock(Users.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+    FilterChain chain = createMock(FilterChain.class);
+    InternalTokenStorage tokenStorage = createMock(InternalTokenStorage.class);
+
+    expect(request.getHeader(InternalTokenClientFilter.INTERNAL_TOKEN_HEADER)).andReturn(null);
+
+    chain.doFilter(request, response);
+    expectLastCall();
+
+    replay(users, request, response, chain, tokenStorage);
+
+    AmbariUserAuthorizationFilter filter = new AmbariUserAuthorizationFilter(tokenStorage, users);
+    filter.doFilter(request, response, chain);
+
+    verify(users, request, response, chain, tokenStorage);
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+    assertNull(authentication);
+  }
+
+  @Test
+  public void testDoFilterWithoutUserToken() throws IOException, ServletException {
+    final Users users = createMock(Users.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+    FilterChain chain = createMock(FilterChain.class);
+    InternalTokenStorage tokenStorage = createMock(InternalTokenStorage.class);
+
+    expect(request.getHeader(InternalTokenClientFilter.INTERNAL_TOKEN_HEADER)).andReturn(TEST_INTERNAL_TOKEN);
+    expect(tokenStorage.isValidInternalToken(TEST_INTERNAL_TOKEN)).andReturn(true);
+    expect(request.getHeader(ExecutionScheduleManager.USER_ID_HEADER)).andReturn(null);
+
+    chain.doFilter(request, response);
+    expectLastCall();
+
+    replay(users, request, response, chain, tokenStorage);
+
+    AmbariUserAuthorizationFilter filter = new AmbariUserAuthorizationFilter(tokenStorage, users);
+    filter.doFilter(request, response, chain);
+
+    verify(users, request, response, chain, tokenStorage);
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+    assertNull(authentication);
+  }
+
+  @Test
+  public void testDoFilterWithIncorrectUser() throws IOException, ServletException {
+    final Users users = createMock(Users.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+    FilterChain chain = createMock(FilterChain.class);
+    InternalTokenStorage tokenStorage = createMock(InternalTokenStorage.class);
+
+    expect(request.getHeader(InternalTokenClientFilter.INTERNAL_TOKEN_HEADER)).andReturn(TEST_INTERNAL_TOKEN);
+    expect(tokenStorage.isValidInternalToken(TEST_INTERNAL_TOKEN)).andReturn(true);
+    expect(request.getHeader(ExecutionScheduleManager.USER_ID_HEADER)).andReturn(TEST_USER_ID_HEADER);
+
+    expect(users.getUser(TEST_USER_ID)).andReturn(null);
+
+    response.sendError(HttpServletResponse.SC_FORBIDDEN, "Authentication required");
+    expectLastCall();
+    response.flushBuffer();
+    expectLastCall();
+
+    replay(users, request, response, chain, tokenStorage);
+
+    AmbariUserAuthorizationFilter filter = new AmbariUserAuthorizationFilter(tokenStorage, users);
+    filter.doFilter(request, response, chain);
+
+    verify(users, request, response, chain, tokenStorage);
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+    assertNull(authentication);
+  }
+
+  @Test
+  public void testDoFilterWithInvalidUserID() throws IOException, ServletException {
+    final Users users = createMock(Users.class);
+    HttpServletRequest request = createMock(HttpServletRequest.class);
+    HttpServletResponse response = createMock(HttpServletResponse.class);
+    FilterChain chain = createMock(FilterChain.class);
+    InternalTokenStorage tokenStorage = createMock(InternalTokenStorage.class);
+
+    expect(request.getHeader(InternalTokenClientFilter.INTERNAL_TOKEN_HEADER)).andReturn(TEST_INTERNAL_TOKEN);
+    expect(tokenStorage.isValidInternalToken(TEST_INTERNAL_TOKEN)).andReturn(true);
+    expect(request.getHeader(ExecutionScheduleManager.USER_ID_HEADER)).andReturn("admin");
+
+    response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid user ID");
+    expectLastCall();
+    response.flushBuffer();
+    expectLastCall();
+
+    replay(users, request, response, chain, tokenStorage);
+
+    AmbariUserAuthorizationFilter filter = new AmbariUserAuthorizationFilter(tokenStorage, users);
+    filter.doFilter(request, response, chain);
+
+    verify(users, request, response, chain, tokenStorage);
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+    assertNull(authentication);
+  }
+
+  private User combineUser() {
+    PrincipalEntity principalEntity = new PrincipalEntity();
+    UserEntity userEntity = new UserEntity();
+    userEntity.setUserId(TEST_USER_ID);
+    userEntity.setUserName(TEST_USER_NAME);
+    userEntity.setUserType(UserType.LOCAL);
+    userEntity.setPrincipal(principalEntity);
+    User user = new User(userEntity);
+
+    return user;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java
index 9f38841..56f224c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java
@@ -30,6 +30,7 @@ import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
 import org.apache.ambari.server.orm.entities.RoleAuthorizationEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
 import org.easymock.EasyMockRule;
 import org.easymock.EasyMockSupport;
 import org.easymock.Mock;
@@ -147,6 +148,32 @@ public class AuthorizationHelperTest  extends EasyMockSupport {
   }
 
   @Test
+  public void testAuthId() throws Exception {
+    Integer userId = AuthorizationHelper.getAuthenticatedId();
+    Assert.assertEquals(Integer.valueOf(-1), userId);
+
+    PrincipalEntity principalEntity = new PrincipalEntity();
+    UserEntity userEntity = new UserEntity();
+    userEntity.setUserId(1);
+    userEntity.setPrincipal(principalEntity);
+    User user = new User(userEntity);
+    Authentication auth = new AmbariUserAuthentication(null, user, null);
+    SecurityContextHolder.getContext().setAuthentication(auth);
+
+    userId = AuthorizationHelper.getAuthenticatedId();
+    Assert.assertEquals(Integer.valueOf(1), userId);
+  }
+
+  @Test
+  public void testAuthWithoutId() throws Exception {
+    Authentication auth = new UsernamePasswordAuthenticationToken("admin", null);
+    SecurityContextHolder.getContext().setAuthentication(auth);
+
+    Integer userId = AuthorizationHelper.getAuthenticatedId();
+    Assert.assertEquals(Integer.valueOf(-1), userId);
+  }
+
+  @Test
   public void testLoginAliasAuthName() throws Exception {
 
     reset(servletRequestAttributes);

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
index dee4490..bcff6b4 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.security.authorization;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.List;
@@ -168,6 +169,23 @@ public class TestUsers {
   }
 
   @Test
+  public void testGetUserById() throws Exception {
+    users.createUser("user", "user", true, false, false);
+    User createdUser = users.getUser("user", UserType.LOCAL);
+    User userById = users.getUser(createdUser.getUserId());
+
+    assertNotNull(userById);
+    assertEquals(createdUser.getUserId(), userById.getUserId());
+  }
+
+  @Test
+  public void testGetUserByInvalidId() throws Exception {
+    User userById = users.getUser(-1);
+
+    assertNull(userById);
+  }
+
+  @Test
   public void testSetUserActive() throws Exception {
     users.createUser("user", "user");
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/5d9348ce/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
index 9b1c16c..670200c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java
@@ -285,6 +285,8 @@ public class UpgradeCatalog240Test {
 
     Capture<DBAccessor.DBColumnInfo> capturedClusterHandleColumn = EasyMock.newCapture();
     dbAccessor.renameColumn(eq(UpgradeCatalog240.VIEWINSTANCE_TABLE), anyString() , capture(capturedClusterHandleColumn));
+    Capture<DBAccessor.DBColumnInfo> requestScheduleUserIdInfo = newCapture();
+    dbAccessor.addColumn(eq(UpgradeCatalog240.REQUESTSCHEDULE_TABLE), capture(requestScheduleUserIdInfo));
 
     replay(dbAccessor, configuration, connection, statement, resultSet);
 
@@ -411,8 +413,8 @@ public class UpgradeCatalog240Test {
     Assert.assertEquals(UpgradeCatalog240.ALERT_TARGET_ENABLED_COLUMN, targetEnabledColumnInfo.getName());
     Assert.assertEquals(Short.class, targetEnabledColumnInfo.getType());
     Assert.assertEquals(1, targetEnabledColumnInfo.getDefaultValue());
-    Assert.assertEquals(false, targetEnabledColumnInfo.isNullable());    
-    
+    Assert.assertEquals(false, targetEnabledColumnInfo.isNullable());
+
     assertEquals(expectedCaptures, actualCaptures);
 
     // Verify blueprint_setting columns
@@ -463,6 +465,13 @@ public class UpgradeCatalog240Test {
     Assert.assertEquals(UpgradeCatalog240.CLUSTER_HANDLE_COLUMN, clusterHandleColumn.getName());
     Assert.assertEquals(Long.class, clusterHandleColumn.getType());
 
+    // Verify authenticated_user_id column
+    DBAccessor.DBColumnInfo requestScheduleUserIdInfoValue = requestScheduleUserIdInfo.getValue();
+    Assert.assertNotNull(requestScheduleUserIdInfoValue);
+    Assert.assertEquals("authenticated_user_id", requestScheduleUserIdInfoValue.getName());
+    Assert.assertEquals(Integer.class, requestScheduleUserIdInfoValue.getType());
+    Assert.assertEquals(null, requestScheduleUserIdInfoValue.getDefaultValue());
+
     verify(dbAccessor);
   }