فهرست منبع

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

Myroslav Papirkovskyi 9 سال پیش
والد
کامیت
5d9348cedc
33فایلهای تغییر یافته به همراه853 افزوده شده و 200 حذف شده
  1. 7 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
  2. 5 0
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
  3. 6 3
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
  4. 12 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/RequestScheduleResponse.java
  5. 10 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProvider.java
  6. 11 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RequestScheduleEntity.java
  7. 5 3
      ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java
  8. 0 99
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsService.java
  9. 113 0
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProvider.java
  10. 71 0
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthentication.java
  11. 98 0
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariUserAuthorizationFilter.java
  12. 20 0
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java
  13. 5 0
      ambari-server/src/main/java/org/apache/ambari/server/security/authorization/Users.java
  14. 10 0
      ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java
  15. 12 2
      ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecutionImpl.java
  16. 8 0
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java
  17. 1 0
      ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
  18. 1 0
      ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
  19. 1 0
      ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
  20. 1 0
      ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
  21. 1 0
      ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
  22. 1 0
      ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
  23. 1 0
      ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
  24. 2 3
      ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml
  25. 2 0
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProviderTest.java
  26. 3 1
      ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java
  27. 14 11
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationProviderDisableUserTest.java
  28. 0 74
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java
  29. 159 0
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserProviderTest.java
  30. 217 0
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariUserAuthenticationFilterTest.java
  31. 27 0
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AuthorizationHelperTest.java
  32. 18 0
      ambari-server/src/test/java/org/apache/ambari/server/security/authorization/TestUsers.java
  33. 11 2
      ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java

+ 7 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java

@@ -548,6 +548,13 @@ public interface AmbariManagementController {
    */
    */
   String getAuthName();
   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
    * Create and persist the request stages and return a response containing the
    * associated request and resulting tasks.
    * associated request and resulting tasks.

+ 5 - 0
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -4326,6 +4326,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     return AuthorizationHelper.getAuthenticatedName(configs.getAnonymousAuditName());
     return AuthorizationHelper.getAuthenticatedName(configs.getAnonymousAuditName());
   }
   }
 
 
+  @Override
+  public int getAuthId() {
+    return AuthorizationHelper.getAuthenticatedId();
+  }
+
   @Override
   @Override
   public Set<RootServiceResponse> getRootServices(
   public Set<RootServiceResponse> getRootServices(
       Set<RootServiceRequest> requests) throws AmbariException {
       Set<RootServiceRequest> requests) throws AmbariException {

+ 6 - 3
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.SecurityFilter;
 import org.apache.ambari.server.security.authentication.AmbariAuthenticationFilter;
 import org.apache.ambari.server.security.authentication.AmbariAuthenticationFilter;
 import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
 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.AmbariLdapAuthenticationProvider;
-import org.apache.ambari.server.security.authorization.AmbariLocalUserDetailsService;
 import org.apache.ambari.server.security.authorization.PermissionHelper;
 import org.apache.ambari.server.security.authorization.PermissionHelper;
 import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.authorization.internal.AmbariInternalAuthenticationProvider;
 import org.apache.ambari.server.security.authorization.internal.AmbariInternalAuthenticationProvider;
@@ -319,14 +320,16 @@ public class AmbariServer {
         injector.getInstance(AuditLogger.class));
         injector.getInstance(AuditLogger.class));
       factory.registerSingleton("permissionHelper",
       factory.registerSingleton("permissionHelper",
         injector.getInstance(PermissionHelper.class));
         injector.getInstance(PermissionHelper.class));
-      factory.registerSingleton("ambariLocalUserService",
-        injector.getInstance(AmbariLocalUserDetailsService.class));
       factory.registerSingleton("ambariLdapAuthenticationProvider",
       factory.registerSingleton("ambariLdapAuthenticationProvider",
         injector.getInstance(AmbariLdapAuthenticationProvider.class));
         injector.getInstance(AmbariLdapAuthenticationProvider.class));
+      factory.registerSingleton("ambariLocalAuthenticationProvider",
+        injector.getInstance(AmbariLocalUserProvider.class));
       factory.registerSingleton("ambariLdapDataPopulator",
       factory.registerSingleton("ambariLdapDataPopulator",
         injector.getInstance(AmbariLdapDataPopulator.class));
         injector.getInstance(AmbariLdapDataPopulator.class));
       factory.registerSingleton("ambariAuthorizationFilter",
       factory.registerSingleton("ambariAuthorizationFilter",
         injector.getInstance(AmbariAuthorizationFilter.class));
         injector.getInstance(AmbariAuthorizationFilter.class));
+      factory.registerSingleton("ambariUserAuthorizationFilter",
+        injector.getInstance(AmbariUserAuthorizationFilter.class));
       factory.registerSingleton("ambariInternalAuthenticationProvider",
       factory.registerSingleton("ambariInternalAuthenticationProvider",
         injector.getInstance(AmbariInternalAuthenticationProvider.class));
         injector.getInstance(AmbariInternalAuthenticationProvider.class));
       factory.registerSingleton("ambariJwtAuthenticationFilter",
       factory.registerSingleton("ambariJwtAuthenticationFilter",

+ 12 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/RequestScheduleResponse.java

@@ -33,13 +33,15 @@ public class RequestScheduleResponse {
   private String createTime;
   private String createTime;
   private String updateUser;
   private String updateUser;
   private String updateTime;
   private String updateTime;
+  private Integer authenticatedUserId;
 
 
   public RequestScheduleResponse(Long id, String clusterName,
   public RequestScheduleResponse(Long id, String clusterName,
                                  String description, String status,
                                  String description, String status,
                                  String lastExecutionStatus,
                                  String lastExecutionStatus,
                                  Batch batch, Schedule schedule,
                                  Batch batch, Schedule schedule,
                                  String createUser, String createTime,
                                  String createUser, String createTime,
-                                 String updateUser, String updateTime) {
+                                 String updateUser, String updateTime,
+                                 Integer authenticatedUserId) {
     this.id = id;
     this.id = id;
     this.clusterName = clusterName;
     this.clusterName = clusterName;
     this.description = description;
     this.description = description;
@@ -51,6 +53,7 @@ public class RequestScheduleResponse {
     this.createTime = createTime;
     this.createTime = createTime;
     this.updateUser = updateUser;
     this.updateUser = updateUser;
     this.updateTime = updateTime;
     this.updateTime = updateTime;
+    this.authenticatedUserId = authenticatedUserId;
   }
   }
 
 
   public Long getId() {
   public Long getId() {
@@ -140,4 +143,12 @@ public class RequestScheduleResponse {
   public void setLastExecutionStatus(String lastExecutionStatus) {
   public void setLastExecutionStatus(String lastExecutionStatus) {
     this.lastExecutionStatus = lastExecutionStatus;
     this.lastExecutionStatus = lastExecutionStatus;
   }
   }
+
+  public Integer getAuthenticatedUserId() {
+    return authenticatedUserId;
+  }
+
+  public void setAuthenticatedUserId(Integer authenticatedUserId) {
+    this.authenticatedUserId = authenticatedUserId;
+  }
 }
 }

+ 10 - 1
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");
     PropertyHelper.getPropertyId("RequestSchedule", "schedule");
   protected static final String REQUEST_SCHEDULE_CREATE_USER_PROPERTY_ID =
   protected static final String REQUEST_SCHEDULE_CREATE_USER_PROPERTY_ID =
     PropertyHelper.getPropertyId("RequestSchedule", "create_user");
     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 =
   protected static final String REQUEST_SCHEDULE_UPDATE_USER_PROPERTY_ID =
     PropertyHelper.getPropertyId("RequestSchedule", "update_user");
     PropertyHelper.getPropertyId("RequestSchedule", "update_user");
   protected static final String REQUEST_SCHEDULE_CREATE_TIME_PROPERTY_ID =
   protected static final String REQUEST_SCHEDULE_CREATE_TIME_PROPERTY_ID =
@@ -207,6 +209,8 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
         response.getSchedule(), requestedIds);
         response.getSchedule(), requestedIds);
       setResourceProperty(resource, REQUEST_SCHEDULE_CREATE_USER_PROPERTY_ID,
       setResourceProperty(resource, REQUEST_SCHEDULE_CREATE_USER_PROPERTY_ID,
         response.getCreateUser(), requestedIds);
         response.getCreateUser(), requestedIds);
+      setResourceProperty(resource, REQUEST_SCHEDULE_AUTHENTICATED_USER_PROPERTY_ID,
+        response.getAuthenticatedUserId(), requestedIds);
       setResourceProperty(resource, REQUEST_SCHEDULE_CREATE_TIME_PROPERTY_ID,
       setResourceProperty(resource, REQUEST_SCHEDULE_CREATE_TIME_PROPERTY_ID,
         response.getCreateTime(), requestedIds);
         response.getCreateTime(), requestedIds);
       setResourceProperty(resource, REQUEST_SCHEDULE_UPDATE_USER_PROPERTY_ID,
       setResourceProperty(resource, REQUEST_SCHEDULE_UPDATE_USER_PROPERTY_ID,
@@ -365,6 +369,7 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
       }
       }
 
 
       String username = getManagementController().getAuthName();
       String username = getManagementController().getAuthName();
+      Integer userId = getManagementController().getAuthId();
 
 
       requestExecution.setBatch(request.getBatch());
       requestExecution.setBatch(request.getBatch());
       requestExecution.setDescription(request.getDescription());
       requestExecution.setDescription(request.getDescription());
@@ -374,6 +379,7 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
         requestExecution.setStatus(RequestExecution.Status.valueOf(request.getStatus()));
         requestExecution.setStatus(RequestExecution.Status.valueOf(request.getStatus()));
       }
       }
       requestExecution.setUpdateUser(username);
       requestExecution.setUpdateUser(username);
+      requestExecution.setAuthenticatedUserId(userId);
 
 
       LOG.info("Persisting updated Request Schedule "
       LOG.info("Persisting updated Request Schedule "
         + ", clusterName = " + request.getClusterName()
         + ", clusterName = " + request.getClusterName()
@@ -417,12 +423,14 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
       }
       }
 
 
       String username = getManagementController().getAuthName();
       String username = getManagementController().getAuthName();
+      Integer userId = getManagementController().getAuthId();
 
 
       RequestExecution requestExecution = requestExecutionFactory.createNew
       RequestExecution requestExecution = requestExecutionFactory.createNew
         (cluster, request.getBatch(), request.getSchedule());
         (cluster, request.getBatch(), request.getSchedule());
 
 
       requestExecution.setCreateUser(username);
       requestExecution.setCreateUser(username);
       requestExecution.setUpdateUser(username);
       requestExecution.setUpdateUser(username);
+      requestExecution.setAuthenticatedUserId(userId);
       requestExecution.setStatus(RequestExecution.Status.SCHEDULED);
       requestExecution.setStatus(RequestExecution.Status.SCHEDULED);
 
 
       LOG.info("Persisting new Request Schedule "
       LOG.info("Persisting new Request Schedule "
@@ -443,7 +451,8 @@ public class RequestScheduleResourceProvider extends AbstractControllerResourceP
           requestExecution.getLastExecutionStatus(),
           requestExecution.getLastExecutionStatus(),
           requestExecution.getBatch(), request.getSchedule(),
           requestExecution.getBatch(), request.getSchedule(),
           requestExecution.getCreateUser(), requestExecution.getCreateTime(),
           requestExecution.getCreateUser(), requestExecution.getCreateTime(),
-          requestExecution.getUpdateUser(), requestExecution.getUpdateTime());
+          requestExecution.getUpdateUser(), requestExecution.getUpdateTime(),
+          requestExecution.getAuthenticatedUserId());
 
 
       responses.add(response);
       responses.add(response);
     }
     }

+ 11 - 0
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")
   @Column(name = "batch_toleration_limit")
   private Integer batchTolerationLimit;
   private Integer batchTolerationLimit;
 
 
+  @Column(name = "authenticated_user_id")
+  private Integer authenticatedUserId;
+
   @Column(name = "create_user")
   @Column(name = "create_user")
   private String createUser;
   private String createUser;
 
 
@@ -296,6 +299,14 @@ public class RequestScheduleEntity {
     this.requestEntities = requestEntities;
     this.requestEntities = requestEntities;
   }
   }
 
 
+  public Integer getAuthenticatedUserId() {
+    return authenticatedUserId;
+  }
+
+  public void setAuthenticatedUserId(Integer authenticatedUser) {
+    this.authenticatedUserId = authenticatedUser;
+  }
+
   @Override
   @Override
   public boolean equals(Object o) {
   public boolean equals(Object o) {
     if (this == o) return true;
     if (this == o) return true;

+ 5 - 3
ambari-server/src/main/java/org/apache/ambari/server/scheduler/ExecutionScheduleManager.java

@@ -96,6 +96,8 @@ public class ExecutionScheduleManager {
     "RequestExecution";
     "RequestExecution";
   protected static final String DEFAULT_API_PATH = "api/v1";
   protected static final String DEFAULT_API_PATH = "api/v1";
 
 
+  public static final String USER_ID_HEADER = "X-Authenticated-User-ID";
+
   protected Client ambariClient;
   protected Client ambariClient;
   protected WebResource ambariWebResource;
   protected WebResource ambariWebResource;
 
 
@@ -521,7 +523,7 @@ public class ExecutionScheduleManager {
 
 
       body = requestExecution.getRequestBody(batchId);
       body = requestExecution.getRequestBody(batchId);
 
 
-      BatchRequestResponse batchRequestResponse = performApiRequest(uri, body, type);
+      BatchRequestResponse batchRequestResponse = performApiRequest(uri, body, type, requestExecution.getAuthenticatedUserId());
 
 
       updateBatchRequest(executionId, batchId, clusterName, batchRequestResponse, false);
       updateBatchRequest(executionId, batchId, clusterName, batchRequestResponse, false);
 
 
@@ -668,10 +670,10 @@ public class ExecutionScheduleManager {
     return convertToBatchRequestResponse(response);
     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;
     ClientResponse response;
     try {
     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) {
     } catch (UniformInterfaceException e) {
       response = e.getResponse();
       response = e.getResponse();
     }
     }

+ 0 - 99
ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsService.java

@@ -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));
-  }
-}

+ 113 - 0
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);
+  }
+}

+ 71 - 0
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();
+  }
+}

+ 98 - 0
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
+  }
+}

+ 20 - 0
ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AuthorizationHelper.java

@@ -97,6 +97,26 @@ public class AuthorizationHelper {
     return (null == auth) ? defaultUsername : auth.getName();
     return (null == auth) ? defaultUsername : auth.getName();
   }
   }
 
 
+  /**
+   * 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
    * 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
    * perform an operation on the specific resource by matching the authenticated user's

+ 5 - 0
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);
     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
    * Modifies password of local user
    * @throws AmbariException
    * @throws AmbariException

+ 10 - 0
ambari-server/src/main/java/org/apache/ambari/server/state/scheduler/RequestExecution.java

@@ -104,6 +104,11 @@ public interface RequestExecution {
    */
    */
   public void setLastExecutionStatus(String status);
   public void setLastExecutionStatus(String status);
 
 
+  /**
+   * Set authenticated user
+   */
+  public void setAuthenticatedUserId(Integer username);
+
   /**
   /**
    * Set create username
    * Set create username
    */
    */
@@ -124,6 +129,11 @@ public interface RequestExecution {
    */
    */
   public String getUpdateTime();
   public String getUpdateTime();
 
 
+  /**
+   * Get authenticated user
+   */
+  public Integer getAuthenticatedUserId();
+
   /**
   /**
    * Get create user
    * Get create user
    */
    */

+ 12 - 2
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.dao.RequestScheduleDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.RequestScheduleBatchRequestEntity;
 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.orm.entities.RequestScheduleEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Clusters;
@@ -174,7 +173,8 @@ public class RequestExecutionImpl implements RequestExecution {
         requestScheduleEntity.getCreateUser(),
         requestScheduleEntity.getCreateUser(),
         DateUtils.convertToReadableTime(requestScheduleEntity.getCreateTimestamp()),
         DateUtils.convertToReadableTime(requestScheduleEntity.getCreateTimestamp()),
         requestScheduleEntity.getUpdateUser(),
         requestScheduleEntity.getUpdateUser(),
-        DateUtils.convertToReadableTime(requestScheduleEntity.getUpdateTimestamp())
+        DateUtils.convertToReadableTime(requestScheduleEntity.getUpdateTimestamp()),
+        requestScheduleEntity.getAuthenticatedUserId()
       );
       );
       return response;
       return response;
     } finally {
     } finally {
@@ -339,6 +339,11 @@ public class RequestExecutionImpl implements RequestExecution {
     requestScheduleEntity.setLastExecutionStatus(status);
     requestScheduleEntity.setLastExecutionStatus(status);
   }
   }
 
 
+  @Override
+  public void setAuthenticatedUserId(Integer username) {
+    requestScheduleEntity.setAuthenticatedUserId(username);
+  }
+
   @Override
   @Override
   public void setCreateUser(String username) {
   public void setCreateUser(String username) {
     requestScheduleEntity.setCreateUser(username);
     requestScheduleEntity.setCreateUser(username);
@@ -361,6 +366,11 @@ public class RequestExecutionImpl implements RequestExecution {
       (requestScheduleEntity.getUpdateTimestamp());
       (requestScheduleEntity.getUpdateTimestamp());
   }
   }
 
 
+  @Override
+  public Integer getAuthenticatedUserId() {
+    return requestScheduleEntity.getAuthenticatedUserId();
+  }
+
   @Override
   @Override
   public String getCreateUser() {
   public String getCreateUser() {
     return requestScheduleEntity.getCreateUser();
     return requestScheduleEntity.getCreateUser();

+ 8 - 0
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 VIEWINSTANCE_TABLE = "viewinstance";
   public static final String SHORT_URL_COLUMN = "short_url";
   public static final String SHORT_URL_COLUMN = "short_url";
   public static final String CLUSTER_HANDLE_COLUMN = "cluster_handle";
   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 CLUSTER_VERSION_TABLE = "cluster_version";
   protected static final String HOST_VERSION_TABLE = "host_version";
   protected static final String HOST_VERSION_TABLE = "host_version";
   protected static final String PHOENIX_QUERY_SERVER_PRINCIPAL_KEY = "phoenix.queryserver.kerberos.principal";
   protected static final String PHOENIX_QUERY_SERVER_PRINCIPAL_KEY = "phoenix.queryserver.kerberos.principal";
@@ -275,6 +277,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog {
     updateViewInstanceEntityTable();
     updateViewInstanceEntityTable();
     createRemoteClusterTable();
     createRemoteClusterTable();
     updateViewInstanceTable();
     updateViewInstanceTable();
+    updateRequestScheduleEntityTable();
   }
   }
 
 
   private void createRemoteClusterTable() throws SQLException {
   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));
       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 {
   private void updateClusterTableDDL() throws SQLException {
     dbAccessor.addColumn(CLUSTER_TABLE, new DBColumnInfo(CLUSTER_UPGRADE_ID_COLUMN, Long.class, null, null, true));
     dbAccessor.addColumn(CLUSTER_TABLE, new DBColumnInfo(CLUSTER_UPGRADE_ID_COLUMN, Long.class, null, null, true));
 
 

+ 1 - 0
ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql

@@ -296,6 +296,7 @@ CREATE TABLE requestschedule (
   status varchar(255),
   status varchar(255),
   batch_separation_seconds smallint,
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_user varchar(255),
   create_timestamp bigint,
   create_timestamp bigint,
   update_user varchar(255),
   update_user varchar(255),

+ 1 - 0
ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql

@@ -296,6 +296,7 @@ CREATE TABLE requestschedule (
   status varchar(255),
   status varchar(255),
   batch_separation_seconds smallint,
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_user varchar(255),
   create_timestamp bigint,
   create_timestamp bigint,
   update_user varchar(255),
   update_user varchar(255),

+ 1 - 0
ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql

@@ -287,6 +287,7 @@ CREATE TABLE requestschedule (
   status VARCHAR2(255),
   status VARCHAR2(255),
   batch_separation_seconds smallint,
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id NUMBER(10),
   create_user VARCHAR2(255),
   create_user VARCHAR2(255),
   create_timestamp NUMBER(19),
   create_timestamp NUMBER(19),
   update_user VARCHAR2(255),
   update_user VARCHAR2(255),

+ 1 - 0
ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql

@@ -296,6 +296,7 @@ CREATE TABLE requestschedule (
   status varchar(255),
   status varchar(255),
   batch_separation_seconds smallint,
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_user varchar(255),
   create_timestamp bigint,
   create_timestamp bigint,
   update_user varchar(255),
   update_user varchar(255),

+ 1 - 0
ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql

@@ -356,6 +356,7 @@ CREATE TABLE ambari.requestschedule (
   status varchar(255),
   status varchar(255),
   batch_separation_seconds smallint,
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user varchar(255),
   create_user varchar(255),
   create_timestamp bigint,
   create_timestamp bigint,
   update_user varchar(255),
   update_user varchar(255),

+ 1 - 0
ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql

@@ -285,6 +285,7 @@ CREATE TABLE requestschedule (
   status VARCHAR(255),
   status VARCHAR(255),
   batch_separation_seconds smallint,
   batch_separation_seconds smallint,
   batch_toleration_limit smallint,
   batch_toleration_limit smallint,
+  authenticated_user_id INTEGER,
   create_user VARCHAR(255),
   create_user VARCHAR(255),
   create_timestamp NUMERIC(19),
   create_timestamp NUMERIC(19),
   update_user VARCHAR(255),
   update_user VARCHAR(255),

+ 1 - 0
ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql

@@ -301,6 +301,7 @@ CREATE TABLE requestschedule (
   STATUS VARCHAR(255),
   STATUS VARCHAR(255),
   batch_separation_seconds SMALLINT,
   batch_separation_seconds SMALLINT,
   batch_toleration_limit SMALLINT,
   batch_toleration_limit SMALLINT,
+  authenticated_user_id INTEGER,
   create_user VARCHAR(255),
   create_user VARCHAR(255),
   create_timestamp BIGINT,
   create_timestamp BIGINT,
   update_user VARCHAR(255),
   update_user VARCHAR(255),

+ 2 - 3
ambari-server/src/main/resources/webapp/WEB-INF/spring-security.xml

@@ -25,6 +25,7 @@
   <http use-expressions="true"
   <http use-expressions="true"
         disable-url-rewriting="true" entry-point-ref="ambariEntryPoint">
         disable-url-rewriting="true" entry-point-ref="ambariEntryPoint">
     <intercept-url pattern="/**" access="isAuthenticated()"/>
     <intercept-url pattern="/**" access="isAuthenticated()"/>
+    <custom-filter ref="ambariUserAuthorizationFilter" before="BASIC_AUTH_FILTER"/>
     <custom-filter ref="ambariAuthenticationFilter" position="BASIC_AUTH_FILTER"/>
     <custom-filter ref="ambariAuthenticationFilter" position="BASIC_AUTH_FILTER"/>
     <custom-filter ref="ambariJwtAuthenticationFilter" after="BASIC_AUTH_FILTER" />
     <custom-filter ref="ambariJwtAuthenticationFilter" after="BASIC_AUTH_FILTER" />
     <custom-filter ref="ambariAuthorizationFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
     <custom-filter ref="ambariAuthorizationFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
@@ -34,9 +35,7 @@
 
 
   <authentication-manager alias="authenticationManager">
   <authentication-manager alias="authenticationManager">
 
 
-    <authentication-provider user-service-ref="ambariLocalUserService">
-      <password-encoder ref="passwordEncoder"/>
-    </authentication-provider>
+    <authentication-provider ref="ambariLocalAuthenticationProvider"/>
 
 
     <authentication-provider ref="ambariLdapAuthenticationProvider"/>
     <authentication-provider ref="ambariLdapAuthenticationProvider"/>
 
 

+ 2 - 0
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestScheduleResourceProviderTest.java

@@ -88,6 +88,7 @@ public class RequestScheduleResourceProviderTest {
     expect(managementController.getRequestExecutionFactory()).andReturn
     expect(managementController.getRequestExecutionFactory()).andReturn
       (executionFactory);
       (executionFactory);
     expect(managementController.getAuthName()).andReturn("admin").anyTimes();
     expect(managementController.getAuthName()).andReturn("admin").anyTimes();
+    expect(managementController.getAuthId()).andReturn(1).anyTimes();
 
 
     Capture<Cluster> clusterCapture = new Capture<Cluster>();
     Capture<Cluster> clusterCapture = new Capture<Cluster>();
     Capture<Batch> batchCapture = new Capture<Batch>();
     Capture<Batch> batchCapture = new Capture<Batch>();
@@ -196,6 +197,7 @@ public class RequestScheduleResourceProviderTest {
     expect(managementController.getClusters()).andReturn(clusters).anyTimes();
     expect(managementController.getClusters()).andReturn(clusters).anyTimes();
     expect(clusters.getCluster("Cluster100")).andReturn(cluster).anyTimes();
     expect(clusters.getCluster("Cluster100")).andReturn(cluster).anyTimes();
     expect(managementController.getAuthName()).andReturn("admin").anyTimes();
     expect(managementController.getAuthName()).andReturn("admin").anyTimes();
+    expect(managementController.getAuthId()).andReturn(1).anyTimes();
     expect(managementController.getExecutionScheduleManager()).andReturn
     expect(managementController.getExecutionScheduleManager()).andReturn
       (executionScheduleManager).anyTimes();
       (executionScheduleManager).anyTimes();
 
 

+ 3 - 1
ambari-server/src/test/java/org/apache/ambari/server/scheduler/ExecutionScheduleManagerTest.java

@@ -356,6 +356,7 @@ public class ExecutionScheduleManagerTest {
     String uri = "clusters";
     String uri = "clusters";
     String type = "post";
     String type = "post";
     String body = "body";
     String body = "body";
+    Integer userId = 1;
     Map<Long, RequestExecution> executionMap = new HashMap<Long, RequestExecution>();
     Map<Long, RequestExecution> executionMap = new HashMap<Long, RequestExecution>();
     executionMap.put(executionId, requestExecutionMock);
     executionMap.put(executionId, requestExecutionMock);
 
 
@@ -378,11 +379,12 @@ public class ExecutionScheduleManagerTest {
 
 
     expect(requestExecutionMock.getBatchRequest(eq(batchId))).andReturn(batchRequestMock).once();
     expect(requestExecutionMock.getBatchRequest(eq(batchId))).andReturn(batchRequestMock).once();
     expect(requestExecutionMock.getRequestBody(eq(batchId))).andReturn(body).once();
     expect(requestExecutionMock.getRequestBody(eq(batchId))).andReturn(body).once();
+    expect(requestExecutionMock.getAuthenticatedUserId()).andReturn(userId).once();
 
 
     expect(batchRequestMock.getUri()).andReturn(uri).once();
     expect(batchRequestMock.getUri()).andReturn(uri).once();
     expect(batchRequestMock.getType()).andReturn(type).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));
     scheduleManager.updateBatchRequest(eq(executionId), eq(batchId), eq(clusterName), eq(batchRequestResponse), eq(false));
     expectLastCall().once();
     expectLastCall().once();

+ 14 - 11
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.MemberDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.PrivilegeDAO;
 import org.apache.ambari.server.orm.dao.UserDAO;
 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.apache.ambari.server.orm.entities.UserEntity;
 import org.junit.Assert;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Before;
@@ -28,36 +29,35 @@ import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.Mockito;
 import org.springframework.security.authentication.DisabledException;
 import org.springframework.security.authentication.DisabledException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.StandardPasswordEncoder;
 import org.springframework.security.crypto.password.StandardPasswordEncoder;
 
 
 public class AmbariAuthorizationProviderDisableUserTest {
 public class AmbariAuthorizationProviderDisableUserTest {
 
 
+  private Users users;
+
   private UserDAO userDAO;
   private UserDAO userDAO;
   
   
   private PasswordEncoder encoder = new StandardPasswordEncoder();
   private PasswordEncoder encoder = new StandardPasswordEncoder();
-  
-  private DaoAuthenticationProvider daoProvider;
+
+  private AmbariLocalUserProvider alup;
 
 
   private AmbariLdapAuthoritiesPopulator ldapPopulator;
   private AmbariLdapAuthoritiesPopulator ldapPopulator;
 
 
   @Before
   @Before
   public void setUp() {
   public void setUp() {
     userDAO = Mockito.mock(UserDAO.class);
     userDAO = Mockito.mock(UserDAO.class);
-    
+    users = Mockito.mock(Users.class);
+
     createUser("activeUser", true);
     createUser("activeUser", true);
     createUser("disabledUser", false);
     createUser("disabledUser", false);
     
     
     MemberDAO memberDao = Mockito.mock(MemberDAO.class);
     MemberDAO memberDao = Mockito.mock(MemberDAO.class);
     PrivilegeDAO privilegeDao = Mockito.mock(PrivilegeDAO.class);
     PrivilegeDAO privilegeDao = Mockito.mock(PrivilegeDAO.class);
     AuthorizationHelper authorizationHelper = new AuthorizationHelper();
     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);
     ldapPopulator = new AmbariLdapAuthoritiesPopulator(authorizationHelper, userDAO, memberDao, privilegeDao);
     
     
@@ -65,13 +65,13 @@ public class AmbariAuthorizationProviderDisableUserTest {
   
   
   @Test public void testDisabledUserViaDaoProvider(){
   @Test public void testDisabledUserViaDaoProvider(){
     try{
     try{
-      daoProvider.authenticate(new UsernamePasswordAuthenticationToken("disabledUser","pwd"));
+      alup.authenticate(new UsernamePasswordAuthenticationToken("disabledUser","pwd"));
       Assert.fail("Disabled user passes authentication");
       Assert.fail("Disabled user passes authentication");
     }catch(DisabledException e){
     }catch(DisabledException e){
       //expected
       //expected
       Assert.assertEquals("User is disabled", e.getMessage());//UI depends on this
       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.assertNotNull(auth);
     Assert.assertTrue(auth.isAuthenticated());
     Assert.assertTrue(auth.isAuthenticated());
   }
   }
@@ -87,10 +87,13 @@ public class AmbariAuthorizationProviderDisableUserTest {
   }
   }
   
   
   private void createUser(String login, boolean isActive) {
   private void createUser(String login, boolean isActive) {
+    PrincipalEntity principalEntity = new PrincipalEntity();
     UserEntity activeUser = new UserEntity();
     UserEntity activeUser = new UserEntity();
+    activeUser.setUserId(1);
     activeUser.setActive(isActive);
     activeUser.setActive(isActive);
     activeUser.setUserName(login);
     activeUser.setUserName(login);
     activeUser.setUserPassword(encoder.encode("pwd"));
     activeUser.setUserPassword(encoder.encode("pwd"));
+    activeUser.setPrincipal(principalEntity);
     Mockito.when(userDAO.findLocalUserByName(login)).thenReturn(activeUser);
     Mockito.when(userDAO.findLocalUserByName(login)).thenReturn(activeUser);
     Mockito.when(userDAO.findLdapUserByName(login)).thenReturn(activeUser);
     Mockito.when(userDAO.findLdapUserByName(login)).thenReturn(activeUser);
   }
   }

+ 0 - 74
ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariLocalUserDetailsServiceTest.java

@@ -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");
-  }
-}

+ 159 - 0
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;
+  }
+}

+ 217 - 0
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;
+  }
+}

+ 27 - 0
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.ResourceTypeEntity;
 import org.apache.ambari.server.orm.entities.RoleAuthorizationEntity;
 import org.apache.ambari.server.orm.entities.RoleAuthorizationEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
 import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
+import org.apache.ambari.server.orm.entities.UserEntity;
 import org.easymock.EasyMockRule;
 import org.easymock.EasyMockRule;
 import org.easymock.EasyMockSupport;
 import org.easymock.EasyMockSupport;
 import org.easymock.Mock;
 import org.easymock.Mock;
@@ -146,6 +147,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
   @Test
   public void testLoginAliasAuthName() throws Exception {
   public void testLoginAliasAuthName() throws Exception {
 
 

+ 18 - 0
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.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertTrue;
 
 
 import java.util.List;
 import java.util.List;
@@ -167,6 +168,23 @@ public class TestUsers {
     Assert.assertNull(users.getAnyUser("non_existing"));
     Assert.assertNull(users.getAnyUser("non_existing"));
   }
   }
 
 
+  @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
   @Test
   public void testSetUserActive() throws Exception {
   public void testSetUserActive() throws Exception {
     users.createUser("user", "user");
     users.createUser("user", "user");

+ 11 - 2
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();
     Capture<DBAccessor.DBColumnInfo> capturedClusterHandleColumn = EasyMock.newCapture();
     dbAccessor.renameColumn(eq(UpgradeCatalog240.VIEWINSTANCE_TABLE), anyString() , capture(capturedClusterHandleColumn));
     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);
     replay(dbAccessor, configuration, connection, statement, resultSet);
 
 
@@ -411,8 +413,8 @@ public class UpgradeCatalog240Test {
     Assert.assertEquals(UpgradeCatalog240.ALERT_TARGET_ENABLED_COLUMN, targetEnabledColumnInfo.getName());
     Assert.assertEquals(UpgradeCatalog240.ALERT_TARGET_ENABLED_COLUMN, targetEnabledColumnInfo.getName());
     Assert.assertEquals(Short.class, targetEnabledColumnInfo.getType());
     Assert.assertEquals(Short.class, targetEnabledColumnInfo.getType());
     Assert.assertEquals(1, targetEnabledColumnInfo.getDefaultValue());
     Assert.assertEquals(1, targetEnabledColumnInfo.getDefaultValue());
-    Assert.assertEquals(false, targetEnabledColumnInfo.isNullable());    
-    
+    Assert.assertEquals(false, targetEnabledColumnInfo.isNullable());
+
     assertEquals(expectedCaptures, actualCaptures);
     assertEquals(expectedCaptures, actualCaptures);
 
 
     // Verify blueprint_setting columns
     // Verify blueprint_setting columns
@@ -463,6 +465,13 @@ public class UpgradeCatalog240Test {
     Assert.assertEquals(UpgradeCatalog240.CLUSTER_HANDLE_COLUMN, clusterHandleColumn.getName());
     Assert.assertEquals(UpgradeCatalog240.CLUSTER_HANDLE_COLUMN, clusterHandleColumn.getName());
     Assert.assertEquals(Long.class, clusterHandleColumn.getType());
     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);
     verify(dbAccessor);
   }
   }