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