You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2014/09/27 02:28:36 UTC
[1/3] git commit: AMBARI-7529. On upgrade to 1.7.0,
automatically create Jobs view instance.
Repository: ambari
Updated Branches:
refs/heads/trunk dcedac206 -> be13513cf
AMBARI-7529. On upgrade to 1.7.0, automatically create Jobs view instance.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1ea0f474
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1ea0f474
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1ea0f474
Branch: refs/heads/trunk
Commit: 1ea0f474ee9316dbb18beda3cec6935d3ffc14f3
Parents: dcedac2
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Fri Sep 26 16:57:41 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Fri Sep 26 16:57:41 2014 -0700
----------------------------------------------------------------------
.../server/upgrade/UpgradeCatalog170.java | 139 +++++++++++++------
.../apache/ambari/server/view/ViewRegistry.java | 26 +++-
.../server/upgrade/UpgradeCatalog170Test.java | 63 +++++++--
.../ambari/server/upgrade/UpgradeTest.java | 11 +-
contrib/views/jobs/src/main/resources/view.xml | 4 +-
5 files changed, 181 insertions(+), 62 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
index 6693e20..d86bf35 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog170.java
@@ -46,6 +46,7 @@ import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
import org.apache.ambari.server.orm.entities.ClusterEntity;
import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
+import org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity;
import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity;
import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
@@ -70,6 +71,7 @@ import org.apache.ambari.server.state.Clusters;
import org.apache.ambari.server.state.Config;
import org.apache.ambari.server.state.ConfigHelper;
import org.apache.ambari.server.utils.StageUtils;
+import org.apache.ambari.server.view.ViewRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -115,9 +117,16 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
private static final String ALERT_TABLE_GROUPING = "alert_grouping";
private static final String ALERT_TABLE_NOTICE = "alert_notice";
public static final String JOBS_VIEW_NAME = "JOBS";
+ public static final String VIEW_NAME_REG_EXP = JOBS_VIEW_NAME + "\\{.*\\}";
public static final String JOBS_VIEW_INSTANCE_NAME = "JOBS_1";
public static final String SHOW_JOBS_FOR_NON_ADMIN_KEY = "showJobsForNonAdmin";
public static final String JOBS_VIEW_INSTANCE_LABEL = "Jobs";
+ public static final String CLUSTER_STATE_STACK_HDP_2_1 = "{\"stackName\":\"HDP\",\"stackVersion\":\"2.1\"}";
+ public static final String YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY = "yarn.timeline-service.webapp.address";
+ public static final String YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY = "yarn.resourcemanager.webapp.address";
+ public static final String YARN_SITE = "yarn-site";
+ public static final String YARN_ATS_URL_PROPERTY = "yarn.ats.url";
+ public static final String YARN_RESOURCEMANAGER_URL_PROPERTY = "yarn.resourcemanager.url";
//SourceVersion is only for book-keeping purpos
@Override
@@ -1295,56 +1304,96 @@ public class UpgradeCatalog170 extends AbstractUpgradeCatalog {
final KeyValueDAO keyValueDAO = injector.getInstance(KeyValueDAO.class);
final PermissionDAO permissionDAO = injector.getInstance(PermissionDAO.class);
final PrivilegeDAO privilegeDAO = injector.getInstance(PrivilegeDAO.class);
-
- ViewEntity jobsView = viewDAO.findByCommonName(JOBS_VIEW_NAME);
- if (jobsView != null) {
- ViewInstanceEntity jobsInstance = jobsView.getInstanceDefinition(JOBS_VIEW_INSTANCE_NAME);
- if (jobsInstance == null) {
- jobsInstance = new ViewInstanceEntity(jobsView, JOBS_VIEW_INSTANCE_NAME, JOBS_VIEW_INSTANCE_LABEL);
- ResourceEntity resourceEntity = new ResourceEntity();
- resourceEntity.setResourceType(resourceTypeDAO.findByName(
- ViewEntity.getViewName(
- jobsView.getCommonName(),
- jobsView.getVersion())));
- jobsInstance.setResource(resourceEntity);
- jobsView.addInstanceDefinition(jobsInstance);
- resourceDAO.create(resourceEntity);
- viewInstanceDAO.create(jobsInstance);
- viewDAO.merge(jobsView);
- }
- // get showJobsForNonAdmin value and remove it
- boolean showJobsForNonAdmin = false;
- KeyValueEntity showJobsKeyValueEntity = keyValueDAO.findByKey(SHOW_JOBS_FOR_NON_ADMIN_KEY);
- if (showJobsKeyValueEntity != null) {
- String value = showJobsKeyValueEntity.getValue();
- showJobsForNonAdmin = Boolean.parseBoolean(value);
- keyValueDAO.remove(showJobsKeyValueEntity);
- }
- if (showJobsForNonAdmin) {
- ResourceEntity jobsResource = jobsInstance.getResource();
- PermissionEntity viewUsePermission = permissionDAO.findViewUsePermission();
- for (UserEntity userEntity : userDAO.findAll()) {
- // check if user has VIEW.USE privilege for JOBS view
- List<PrivilegeEntity> privilegeEntities = privilegeDAO.findAllByPrincipal(
- Collections.singletonList(userEntity.getPrincipal()));
- boolean hasJobsUsePrivilege = false;
- for (PrivilegeEntity privilegeEntity : privilegeEntities) {
- if (privilegeEntity.getResource().getId() == jobsInstance.getResource().getId() &&
- privilegeEntity.getPermission().getId() == viewUsePermission.getId()) {
- hasJobsUsePrivilege = true;
- break;
+ final ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+ final ViewRegistry viewRegistry = injector.getInstance(ViewRegistry.class);
+
+ List<ClusterEntity> clusters = clusterDAO.findAll();
+ if (!clusters.isEmpty()) {
+ ClusterEntity currentCluster = clusters.get(0);
+ String currentStackVersion = currentCluster.getClusterStateEntity().getCurrentStackVersion();
+ if (CLUSTER_STATE_STACK_HDP_2_1.equals(currentStackVersion)) {
+ ViewRegistry.initInstance(viewRegistry);
+ viewRegistry.readViewArchives(VIEW_NAME_REG_EXP);
+ ViewEntity jobsView = viewDAO.findByCommonName(JOBS_VIEW_NAME);
+
+ if (jobsView != null) {
+ ViewInstanceEntity jobsInstance = jobsView.getInstanceDefinition(JOBS_VIEW_INSTANCE_NAME);
+ if (jobsInstance == null) {
+ jobsInstance = new ViewInstanceEntity(jobsView, JOBS_VIEW_INSTANCE_NAME, JOBS_VIEW_INSTANCE_LABEL);
+ ResourceEntity resourceEntity = new ResourceEntity();
+ resourceEntity.setResourceType(resourceTypeDAO.findByName(
+ ViewEntity.getViewName(
+ jobsView.getCommonName(),
+ jobsView.getVersion())));
+ String atsHost;
+ String rmHost;
+ try {
+ ClusterConfigEntity currentYarnConfig = null;
+ for (ClusterConfigMappingEntity configMappingEntity : currentCluster.getConfigMappingEntities()) {
+ if (YARN_SITE.equals(configMappingEntity.getType()) && configMappingEntity.isSelected() > 0) {
+ currentYarnConfig = clusterDAO.findConfig(currentCluster.getClusterId(),
+ configMappingEntity.getType(), configMappingEntity.getTag());
+ break;
+ }
+ }
+ Type type = new TypeToken<Map<String, String>>() {}.getType();
+ Map<String, String> yarnSiteProps = StageUtils.getGson().fromJson(currentYarnConfig.getData(), type);
+ atsHost = yarnSiteProps.get(YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY);
+ rmHost = yarnSiteProps.get(YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY);
+ } catch (Exception ex) {
+ // Required properties failed to be set, therefore jobs instance should not be created
+ return;
}
+ jobsInstance.setResource(resourceEntity);
+ jobsInstance.putProperty(YARN_ATS_URL_PROPERTY, "http://" + atsHost);
+ jobsInstance.putProperty(YARN_RESOURCEMANAGER_URL_PROPERTY, "http://" + rmHost);
+ jobsView.addInstanceDefinition(jobsInstance);
+ resourceDAO.create(resourceEntity);
+ viewInstanceDAO.create(jobsInstance);
+ viewDAO.merge(jobsView);
}
- // if not - add VIEW.use privilege
- if (!hasJobsUsePrivilege) {
- PrivilegeEntity privilegeEntity = new PrivilegeEntity();
- privilegeEntity.setResource(jobsResource);
- privilegeEntity.setPermission(viewUsePermission);
- privilegeEntity.setPrincipal(userEntity.getPrincipal());
- privilegeDAO.create(privilegeEntity);
+ // get showJobsForNonAdmin value and remove it
+ boolean showJobsForNonAdmin = false;
+ KeyValueEntity showJobsKeyValueEntity = keyValueDAO.findByKey(SHOW_JOBS_FOR_NON_ADMIN_KEY);
+ if (showJobsKeyValueEntity != null) {
+ String value = showJobsKeyValueEntity.getValue();
+ showJobsForNonAdmin = Boolean.parseBoolean(value);
+ keyValueDAO.remove(showJobsKeyValueEntity);
+ }
+ if (showJobsForNonAdmin) {
+ ResourceEntity jobsResource = jobsInstance.getResource();
+ long jobsResourceId = jobsResource.getId();
+ PermissionEntity viewUsePermission = permissionDAO.findViewUsePermission();
+ PermissionEntity adminPermission = permissionDAO.findAmbariAdminPermission();
+ int viewUsePermissionId = viewUsePermission.getId();
+ int adminPermissionId = adminPermission.getId();
+ for (UserEntity userEntity : userDAO.findAll()) {
+ // check if user has VIEW.USE privilege for JOBS view
+ List<PrivilegeEntity> privilegeEntities = privilegeDAO.findAllByPrincipal(
+ Collections.singletonList(userEntity.getPrincipal()));
+ boolean hasJobsUsePrivilege = false;
+ for (PrivilegeEntity privilegeEntity : privilegeEntities) {
+ int privilegePermissionId = privilegeEntity.getPermission().getId();
+ Long privilegeResourceId = privilegeEntity.getResource().getId();
+ if ((privilegePermissionId == viewUsePermissionId && privilegeResourceId == jobsResourceId)
+ || privilegePermissionId == adminPermissionId) {
+ hasJobsUsePrivilege = true;
+ break;
+ }
+ }
+ // if not - add VIEW.use privilege
+ if (!hasJobsUsePrivilege) {
+ PrivilegeEntity privilegeEntity = new PrivilegeEntity();
+ privilegeEntity.setResource(jobsResource);
+ privilegeEntity.setPermission(viewUsePermission);
+ privilegeEntity.setPrincipal(userEntity.getPrincipal());
+ privilegeDAO.create(privilegeEntity);
+ }
+ }
}
}
}
}
+
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
index 58c4334..5f775a6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java
@@ -102,6 +102,7 @@ public class ViewRegistry {
*/
private static final String EXTRACTED_ARCHIVES_DIR = "work";
private static final String EXTRACT_COMMAND = "extract";
+ private static final String ALL_VIEWS_REG_EXP = ".*";
/**
* Thread pool
@@ -424,10 +425,19 @@ public class ViewRegistry {
}
/**
- * Read the view archives.
+ * Read all view archives.
*/
public void readViewArchives() {
- readViewArchives(false, true);
+ readViewArchives(false, true, ALL_VIEWS_REG_EXP, true);
+ }
+
+ /**
+ * Read only view archives with names corresponding to given regular expression.
+ *
+ * @param viewNameRegExp view name regular expression
+ */
+ public void readViewArchives(String viewNameRegExp) {
+ readViewArchives(false, false, viewNameRegExp, false);
}
/**
@@ -1147,9 +1157,9 @@ public class ViewRegistry {
}
}
-
// read the view archives.
- private void readViewArchives(boolean systemOnly, boolean useExecutor) {
+ private void readViewArchives(boolean systemOnly, boolean useExecutor,
+ String viewNameRegExp, boolean removeUndeployed) {
try {
File viewDir = configuration.getViewsDir();
@@ -1173,6 +1183,10 @@ public class ViewRegistry {
String version = viewConfig.getVersion();
String viewName = ViewEntity.getViewName(commonName, version);
+ if (!viewName.matches(viewNameRegExp)) {
+ continue;
+ }
+
final String extractedArchiveDirPath = extractedArchivesPath + File.separator + viewName;
final File extractedArchiveDirFile = archiveUtility.getFile(extractedArchiveDirPath);
@@ -1210,7 +1224,9 @@ public class ViewRegistry {
}
}
- removeUndeployedViews();
+ if (removeUndeployed) {
+ removeUndeployedViews();
+ }
}
} else {
LOG.error("Could not create extracted view archive directory " + extractedArchivesPath + ".");
http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
index 2edc5b5..0c92f44 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog170Test.java
@@ -18,6 +18,13 @@
package org.apache.ambari.server.upgrade;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.CLUSTER_STATE_STACK_HDP_2_1;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.JOBS_VIEW_NAME;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.SHOW_JOBS_FOR_NON_ADMIN_KEY;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.YARN_SITE;
+import static org.apache.ambari.server.upgrade.UpgradeCatalog170.YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY;
+
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
@@ -49,8 +56,10 @@ import org.apache.ambari.server.orm.dao.UserDAO;
import org.apache.ambari.server.orm.dao.ViewDAO;
import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
+import org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity;
import org.apache.ambari.server.orm.entities.ClusterEntity;
import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
+import org.apache.ambari.server.orm.entities.ClusterStateEntity;
import org.apache.ambari.server.orm.entities.ConfigGroupConfigMappingEntity;
import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntityPK;
@@ -59,6 +68,7 @@ import org.apache.ambari.server.orm.entities.HostComponentStateEntityPK;
import org.apache.ambari.server.orm.entities.HostEntity;
import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
import org.apache.ambari.server.orm.entities.KeyValueEntity;
+import org.apache.ambari.server.orm.entities.PermissionEntity;
import org.apache.ambari.server.orm.entities.PrivilegeEntity;
import org.apache.ambari.server.orm.entities.ResourceEntity;
import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
@@ -74,7 +84,9 @@ import org.apache.ambari.server.state.Config;
import org.apache.ambari.server.state.ConfigHelper;
import org.apache.ambari.server.state.HostComponentAdminState;
import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.view.ViewRegistry;
import org.easymock.Capture;
+import org.easymock.IAnswer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -116,6 +128,7 @@ import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.getCurrentArguments;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
@@ -422,6 +435,9 @@ public class UpgradeCatalog170Test {
Clusters clusters = createStrictMock(Clusters.class);
Config config = createStrictMock(Config.class);
Config pigConfig = createStrictMock(Config.class);
+ ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
+ PermissionEntity adminPermission = createNiceMock(PermissionEntity.class);
+ PermissionEntity viewUsePermission = createNiceMock(PermissionEntity.class);
ClusterConfigEntity clusterConfigEntity = createNiceMock(ClusterConfigEntity.class);
ConfigGroupConfigMappingDAO configGroupConfigMappingDAO = createNiceMock(ConfigGroupConfigMappingDAO.class);
@@ -448,6 +464,8 @@ public class UpgradeCatalog170Test {
TypedQuery<HostRoleCommandEntity> q = createNiceMock(TypedQuery.class);
List<HostRoleCommandEntity> r = new ArrayList<HostRoleCommandEntity>();
ResultSet userRolesResultSet = createNiceMock(ResultSet.class);
+ ClusterEntity clusterEntity = createNiceMock(ClusterEntity.class);
+ ClusterConfigEntity configEntity = createNiceMock(ClusterConfigEntity.class);
Method m = AbstractUpgradeCatalog.class.getDeclaredMethod
("updateConfigurationProperties", String.class, Map.class, boolean.class, boolean.class);
@@ -543,13 +561,20 @@ public class UpgradeCatalog170Test {
expect(injector.getInstance(PermissionDAO.class)).andReturn(permissionDAO).anyTimes();
expect(injector.getInstance(PrivilegeDAO.class)).andReturn(privilegeDAO).anyTimes();
expect(injector.getInstance(KeyValueDAO.class)).andReturn(keyValueDAO).anyTimes();
+ expect(injector.getInstance(ViewRegistry.class)).andReturn(viewRegistry).anyTimes();
+ String yarnConfig = String.format("{'%s':'%s', '%s':'%s'}",
+ YARN_TIMELINE_SERVICE_WEBAPP_ADDRESS_PROPERTY, "timeline:8081",
+ YARN_RESOURCEMANAGER_WEBAPP_ADDRESS_PROPERTY, "resource_man:8081");
expect(configGroupConfigMappingDAO.findAll()).andReturn(configGroupConfigMappingEntities).once();
- expect(userDAO.findAll()).andReturn(Collections.<UserEntity> emptyList()).times(2);
- expect(clusterDAO.findAll()).andReturn(Collections.<ClusterEntity> emptyList()).anyTimes();
+ expect(userDAO.findAll()).andReturn(Collections.<UserEntity>emptyList()).times(2);
+ expect(clusterDAO.findAll()).andReturn(Collections.singletonList(clusterEntity)).anyTimes();
+ expect(configEntity.getData()).andReturn(yarnConfig);
+ expect(clusterDAO.findConfig(1L, YARN_SITE, "version1")).andReturn(configEntity).anyTimes();
expect(viewDAO.findAll()).andReturn(Collections.<ViewEntity> emptyList()).anyTimes();
expect(viewInstanceDAO.findAll()).andReturn(Collections.<ViewInstanceEntity> emptyList()).anyTimes();
- expect(permissionDAO.findAmbariAdminPermission()).andReturn(null);
+ expect(permissionDAO.findAmbariAdminPermission()).andReturn(adminPermission).anyTimes();
+ expect(permissionDAO.findViewUsePermission()).andReturn(viewUsePermission).anyTimes();
expect(permissionDAO.findClusterOperatePermission()).andReturn(null);
expect(permissionDAO.findClusterReadPermission()).andReturn(null);
@@ -559,18 +584,36 @@ public class UpgradeCatalog170Test {
ViewEntity jobsView = createNiceMock(ViewEntity.class);
KeyValueEntity showJobsKeyValue = createNiceMock(KeyValueEntity.class);
UserEntity user = createNiceMock(UserEntity.class);
-
+ ClusterConfigMappingEntity configMappingEntity = createNiceMock(ClusterConfigMappingEntity.class);
+ ClusterStateEntity clusterStateEntity = createNiceMock(ClusterStateEntity.class);
+
+ expect(clusterEntity.getClusterId()).andReturn(1L).anyTimes();
+ expect(clusterEntity.getConfigMappingEntities()).andReturn(Collections.singleton(configMappingEntity));
+ expect(clusterEntity.getClusterStateEntity()).andReturn(clusterStateEntity).anyTimes();
+ expect(clusterStateEntity.getCurrentStackVersion()).andReturn(CLUSTER_STATE_STACK_HDP_2_1);
+ expect(configMappingEntity.getType()).andReturn(YARN_SITE).anyTimes();
+ expect(configMappingEntity.isSelected()).andReturn(1).anyTimes();
+ expect(configMappingEntity.getTag()).andReturn("version1");
expect(userDAO.findAll()).andReturn(Collections.singletonList(user));
- expect(jobsView.getCommonName()).andReturn(UpgradeCatalog170.JOBS_VIEW_NAME);
+ expect(jobsView.getCommonName()).andReturn(JOBS_VIEW_NAME);
expect(jobsView.getVersion()).andReturn("1.0.0");
- expect(viewDAO.findByCommonName(UpgradeCatalog170.JOBS_VIEW_NAME)).andReturn(jobsView).once();
+ expect(viewDAO.findByCommonName(JOBS_VIEW_NAME)).andReturn(jobsView).once();
expect(showJobsKeyValue.getValue()).andReturn("true");
- expect(keyValueDAO.findByKey(UpgradeCatalog170.SHOW_JOBS_FOR_NON_ADMIN_KEY)).andReturn(showJobsKeyValue);
+ expect(keyValueDAO.findByKey(SHOW_JOBS_FOR_NON_ADMIN_KEY)).andReturn(showJobsKeyValue);
expect(privilegeDAO.findAllByPrincipal(anyObject(List.class))).andReturn(Collections.<PrivilegeEntity>emptyList());
expect(viewDAO.merge(jobsView)).andReturn(jobsView);
resourceDAO.create(anyObject(ResourceEntity.class));
+ expect(adminPermission.getId()).andReturn(3);
+ expect(viewUsePermission.getId()).andReturn(4);
viewInstanceDAO.create(anyObject(ViewInstanceEntity.class));
+ expectLastCall().andAnswer(new IAnswer<Object>() {
+ @Override
+ public Object answer() throws Throwable {
+ ((ViewInstanceEntity) getCurrentArguments()[0]).getResource().setId(1L);
+ return null;
+ }
+ });
keyValueDAO.remove(showJobsKeyValue);
privilegeDAO.create(anyObject(PrivilegeEntity.class));
@@ -579,7 +622,8 @@ public class UpgradeCatalog170Test {
replay(dbAccessor, configuration, injector, cluster, clusters, amc, config, configHelper, pigConfig);
replay(userDAO, clusterDAO, viewDAO, viewInstanceDAO, permissionDAO, configGroupConfigMappingDAO);
replay(resourceTypeDAO, resourceDAO, keyValueDAO, privilegeDAO, clusterConfigEntity);
- replay(jobsView, showJobsKeyValue, user);
+ replay(jobsView, showJobsKeyValue, user, viewRegistry, viewUsePermission, adminPermission);
+ replay(clusterEntity, configEntity, configMappingEntity, clusterStateEntity);
Class<?> c = AbstractUpgradeCatalog.class;
Field f = c.getDeclaredField("configuration");
@@ -595,7 +639,8 @@ public class UpgradeCatalog170Test {
upgradeCatalog.executeDMLUpdates();
verify(upgradeCatalog, dbAccessor, configuration, injector, cluster, clusters, amc, config, configHelper,
- jobsView, showJobsKeyValue, privilegeDAO, viewDAO, viewInstanceDAO, resourceDAO, keyValueDAO, userRolesResultSet);
+ jobsView, showJobsKeyValue, privilegeDAO, viewDAO, viewInstanceDAO, resourceDAO, keyValueDAO,
+ viewRegistry, userRolesResultSet, clusterEntity, configEntity, configMappingEntity, clusterStateEntity);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
index c89a0b4..b70d252 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeTest.java
@@ -28,6 +28,8 @@ import org.apache.ambari.server.controller.ControllerModule;
import org.apache.ambari.server.orm.DBAccessor;
import org.apache.ambari.server.orm.dao.*;
import org.apache.ambari.server.utils.VersionUtils;
+import org.apache.ambari.server.view.ViewRegistry;
+import org.easymock.EasyMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -148,7 +150,14 @@ public class UpgradeTest {
}
private void performUpgrade(String targetVersion) throws Exception {
- Injector injector = Guice.createInjector(new SchemaUpgradeHelper.UpgradeHelperModule(properties));
+ Injector injector = Guice.createInjector(new SchemaUpgradeHelper.UpgradeHelperModule(properties) {
+ @Override
+ protected void configure() {
+ super.configure();
+ ViewRegistry viewRegistryMock = EasyMock.createNiceMock(ViewRegistry.class);
+ bind(ViewRegistry.class).toInstance(viewRegistryMock);
+ }
+ });
SchemaUpgradeHelper schemaUpgradeHelper = injector.getInstance(SchemaUpgradeHelper.class);
LOG.info("Upgrading schema to target version = " + targetVersion);
http://git-wip-us.apache.org/repos/asf/ambari/blob/1ea0f474/contrib/views/jobs/src/main/resources/view.xml
----------------------------------------------------------------------
diff --git a/contrib/views/jobs/src/main/resources/view.xml b/contrib/views/jobs/src/main/resources/view.xml
index 30adca2..6dd5ee6 100644
--- a/contrib/views/jobs/src/main/resources/view.xml
+++ b/contrib/views/jobs/src/main/resources/view.xml
@@ -21,11 +21,11 @@ limitations under the License. Kerberos, LDAP, Custom. Binary/Htt
<parameter>
<name>yarn.ats.url</name>
<description>The URL to the YARN Application Timeline Server, used to provide Jobs information, typically, this is the yarn.timeline-service.webapp.address property in the yarn-site.xml configuration. For example: http://yarn.ats.address:8188</description>
- <required>false</required>
+ <required>true</required>
</parameter>
<parameter>
<name>yarn.resourcemanager.url</name>
<description>The URL to the YARN ResourceManager, used to provide YARN Application data. For example: http://yarn.resourcemanager.address:8088</description>
- <required>false</required>
+ <required>true</required>
</parameter>
</view>
[3/3] git commit: AMBARI-7530. Admin: /users and /groups resources
should only be accessible from AMBARI.ADMIN. Missing import.
Posted by sw...@apache.org.
AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN. Missing import.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/be13513c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/be13513c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/be13513c
Branch: refs/heads/trunk
Commit: be13513cf3db7cfc7a16d64766db95b5dd1e19bf
Parents: f92ad8f
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Fri Sep 26 17:28:04 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Fri Sep 26 17:28:04 2014 -0700
----------------------------------------------------------------------
.../server/security/authorization/AmbariAuthorizationFilter.java | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/be13513c/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
index f1c2a26..b184a59 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
@@ -19,6 +19,7 @@
package org.apache.ambari.server.security.authorization;
import java.io.IOException;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
[2/3] git commit: AMBARI-7530. Admin: /users and /groups resources
should only be accessible from AMBARI.ADMIN.
Posted by sw...@apache.org.
AMBARI-7530. Admin: /users and /groups resources should only be accessible from AMBARI.ADMIN.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f92ad8f5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f92ad8f5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f92ad8f5
Branch: refs/heads/trunk
Commit: f92ad8f520b230feaf6c0bc7d8c7248448566e0b
Parents: 1ea0f47
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Fri Sep 26 17:15:55 2014 -0700
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Fri Sep 26 17:15:55 2014 -0700
----------------------------------------------------------------------
.../server/orm/entities/ViewInstanceEntity.java | 34 +--
.../AmbariAuthorizationFilter.java | 81 +++++-
.../server/security/authorization/Users.java | 3 +-
.../orm/entities/ViewInstanceEntityTest.java | 19 +-
.../AmbariAuthorizationFilterTest.java | 266 ++++++++++++++++++-
.../security/authorization/TestUsers.java | 1 +
6 files changed, 335 insertions(+), 69 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
index f84be60..8f8712c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java
@@ -23,9 +23,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -47,6 +44,7 @@ import javax.persistence.UniqueConstraint;
import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.security.SecurityHelper;
import org.apache.ambari.server.security.SecurityHelperImpl;
+import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
import org.apache.ambari.server.view.configuration.InstanceConfig;
import org.apache.ambari.view.ResourceProvider;
import org.apache.ambari.view.ViewDefinition;
@@ -70,15 +68,6 @@ import org.apache.ambari.view.ViewInstanceDefinition;
)
@Entity
public class ViewInstanceEntity implements ViewInstanceDefinition {
- /**
- * The prefix for every view instance context path.
- */
- public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
-
- /**
- * The pattern for matching view instance context path.
- */
- public static final String VIEWS_CONTEXT_PATH_PATTERN = "" + VIEWS_CONTEXT_PATH_PREFIX + "([^/]+)/([^/]+)/([^/]+)(.*)";
@Id
@Column(name = "view_instance_id", nullable = false)
@@ -680,26 +669,7 @@ public class ViewInstanceEntity implements ViewInstanceDefinition {
* @return the context path
*/
public static String getContextPath(String viewName, String version, String viewInstanceName) {
- return VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + version + "/" + viewInstanceName;
- }
-
- /**
- * Parses context path into view name, version and instance name
- *
- * @param contextPath the context path
- * @return null if context path doesn't match correct pattern
- */
- public static ViewInstanceVersionDTO parseContextPath(String contextPath) {
- final Pattern pattern = Pattern.compile(VIEWS_CONTEXT_PATH_PATTERN);
- Matcher matcher = pattern.matcher(contextPath);
- if (!matcher.matches()) {
- return null;
- } else {
- final String viewName = matcher.group(1);
- final String version = matcher.group(2);
- final String instanceName = matcher.group(3);
- return new ViewInstanceVersionDTO(viewName, version, instanceName);
- }
+ return AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + viewName + "/" + version + "/" + viewInstanceName;
}
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
index 658fc80..f1c2a26 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilter.java
@@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.ambari.server.orm.entities.PermissionEntity;
import org.apache.ambari.server.orm.entities.PrivilegeEntity;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity;
import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
import org.apache.ambari.server.security.authorization.internal.InternalAuthenticationToken;
import org.apache.ambari.server.view.ViewRegistry;
@@ -50,6 +49,19 @@ public class AmbariAuthorizationFilter implements Filter {
private static final Pattern STACK_ADVISOR_REGEX = Pattern.compile("/api/v[0-9]+/stacks/[^/]+/versions/[^/]+/validations.*");
+ public static final String API_VERSION_PREFIX = "/api/v[0-9]+";
+ public static final String VIEWS_CONTEXT_PATH_PREFIX = "/views/";
+
+ private static final String VIEWS_CONTEXT_PATH_PATTERN = VIEWS_CONTEXT_PATH_PREFIX + "([^/]+)/([^/]+)/([^/]+)(.*)";
+ private static final String VIEWS_CONTEXT_ALL_PATTERN = VIEWS_CONTEXT_PATH_PREFIX + ".*";
+ private static final String API_USERS_USERNAME_PATTERN = API_VERSION_PREFIX + "/users/([^/?]+)(.*)";
+ private static final String API_USERS_ALL_PATTERN = API_VERSION_PREFIX + "/users.*";
+ private static final String API_GROUPS_ALL_PATTERN = API_VERSION_PREFIX + "/groups.*";
+ private static final String API_CLUSTERS_ALL_PATTERN = API_VERSION_PREFIX + "/clusters.*";
+ private static final String API_VIEWS_ALL_PATTERN = API_VERSION_PREFIX + "/views.*";
+ private static final String API_PERSIST_ALL_PATTERN = API_VERSION_PREFIX + "/persist.*";
+ private static final String API_LDAP_SYNC_EVENTS_ALL_PATTERN = API_VERSION_PREFIX + "/ldap_sync_events.*";
+
/**
* The realm to use for the basic http auth
*/
@@ -92,8 +104,8 @@ public class AmbariAuthorizationFilter implements Filter {
break;
}
- if (requestURI.matches("/api/v[0-9]+/clusters.*")) {
// clusters require permission
+ if (requestURI.matches(API_CLUSTERS_ALL_PATTERN)) {
if (permissionId.equals(PermissionEntity.CLUSTER_READ_PERMISSION) ||
permissionId.equals(PermissionEntity.CLUSTER_OPERATE_PERMISSION)) {
authorized = true;
@@ -105,13 +117,13 @@ public class AmbariAuthorizationFilter implements Filter {
authorized = true;
break;
}
- } else if (requestURI.matches("/api/v[0-9]+/views.*")) {
+ } else if (requestURI.matches(API_VIEWS_ALL_PATTERN)) {
// views require permission
if (permissionId.equals(PermissionEntity.VIEW_USE_PERMISSION)) {
authorized = true;
break;
}
- } else if (requestURI.matches("/api/v[0-9]+/persist.*")) {
+ } else if (requestURI.matches(API_PERSIST_ALL_PATTERN)) {
if (permissionId.equals(PermissionEntity.CLUSTER_OPERATE_PERMISSION)) {
authorized = true;
break;
@@ -120,14 +132,26 @@ public class AmbariAuthorizationFilter implements Filter {
}
}
- if (!authorized && requestURI.matches(ViewInstanceEntity.VIEWS_CONTEXT_PATH_PATTERN)) {
- final ViewInstanceVersionDTO dto = ViewInstanceEntity.parseContextPath(requestURI);
- authorized = ViewRegistry.getInstance().checkPermission(dto.getViewName(), dto.getVersion(), dto.getInstanceName(), true);
+ if (!authorized && requestURI.matches(VIEWS_CONTEXT_PATH_PATTERN)) {
+ final ViewInstanceVersionDTO dto = parseViewInstanceInfo(requestURI);
+ authorized = getViewRegistry().checkPermission(dto.getViewName(), dto.getVersion(), dto.getInstanceName(), true);
}
- // allow GET for everything except views
+ // allow all types of requests for /users/{current_user}
+ if (!authorized && requestURI.matches(API_USERS_USERNAME_PATTERN)) {
+ final SecurityContext securityContext = getSecurityContext();
+ final String currentUserName = securityContext.getAuthentication().getName();
+ final String urlUserName = parseUserName(requestURI);
+ authorized = currentUserName.equalsIgnoreCase(urlUserName);
+ }
+
+ // allow GET for everything except /views, /api/v1/users, /api/v1/groups, /api/v1/ldap_sync_events
if (!authorized &&
- (!httpRequest.getMethod().equals("GET") || requestURI.matches("/views.*"))) {
+ (!httpRequest.getMethod().equals("GET")
+ || requestURI.matches(VIEWS_CONTEXT_ALL_PATTERN)
+ || requestURI.matches(API_USERS_ALL_PATTERN)
+ || requestURI.matches(API_GROUPS_ALL_PATTERN)
+ || requestURI.matches(API_LDAP_SYNC_EVENTS_ALL_PATTERN))) {
httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "You do not have permissions to access this resource.");
@@ -166,7 +190,46 @@ public class AmbariAuthorizationFilter implements Filter {
return value == null || value.length() == 0 ? defaultValue : value;
}
+ /**
+ * Parses context path into view name, version and instance name
+ *
+ * @param contextPath the context path
+ * @return null if context path doesn't match correct pattern
+ */
+ static ViewInstanceVersionDTO parseViewInstanceInfo(String contextPath) {
+ final Pattern pattern = Pattern.compile(VIEWS_CONTEXT_PATH_PATTERN);
+ final Matcher matcher = pattern.matcher(contextPath);
+ if (!matcher.matches()) {
+ return null;
+ } else {
+ final String viewName = matcher.group(1);
+ final String version = matcher.group(2);
+ final String instanceName = matcher.group(3);
+ return new ViewInstanceVersionDTO(viewName, version, instanceName);
+ }
+ }
+
+ /**
+ * Parses url to get user name.
+ *
+ * @param url the url
+ * @return null if url doesn't match correct pattern
+ */
+ static String parseUserName(String url) {
+ final Pattern pattern = Pattern.compile(API_USERS_USERNAME_PATTERN);
+ final Matcher matcher = pattern.matcher(url);
+ if (!matcher.matches()) {
+ return null;
+ } else {
+ return matcher.group(1);
+ }
+ }
+
SecurityContext getSecurityContext() {
return SecurityContextHolder.getContext();
}
+
+ ViewRegistry getViewRegistry() {
+ return ViewRegistry.getInstance();
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/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 26daa1b..1cd3fc8 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
@@ -24,7 +24,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import javax.persistence.EntityManager;
import org.apache.ambari.server.AmbariException;
@@ -66,7 +65,7 @@ import com.google.inject.persist.Transactional;
@Singleton
public class Users {
- private final static Logger LOG = LoggerFactory.getLogger(Users.class);
+ private static final Logger LOG = LoggerFactory.getLogger(Users.class);
@Inject
Provider<EntityManager> entityManagerProvider;
http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
index c0545da..08aea6e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewInstanceEntityTest.java
@@ -20,8 +20,8 @@ package org.apache.ambari.server.orm.entities;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.spi.Resource;
-import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
import org.apache.ambari.server.security.SecurityHelper;
+import org.apache.ambari.server.security.authorization.AmbariAuthorizationFilter;
import org.apache.ambari.server.view.ViewRegistryTest;
import org.apache.ambari.server.view.configuration.InstanceConfig;
import org.apache.ambari.server.view.configuration.InstanceConfigTest;
@@ -295,26 +295,11 @@ public class ViewInstanceEntityTest {
public void testContextPath() throws Exception {
ViewInstanceEntity viewInstanceDefinition = getViewInstanceEntity();
- Assert.assertEquals(ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
+ Assert.assertEquals(AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
viewInstanceDefinition.getContextPath());
}
@Test
- public void testParseContextPath() throws Exception {
- final String[] pathesToTest = {
- ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
- ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/index.html",
- ViewInstanceEntity.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/api/test"
- };
- for (String contextPath: pathesToTest) {
- final ViewInstanceVersionDTO dto = ViewInstanceEntity.parseContextPath(contextPath);
- Assert.assertEquals("INSTANCE1", dto.getInstanceName());
- Assert.assertEquals("MY_VIEW", dto.getViewName());
- Assert.assertEquals("1.0.0", dto.getVersion());
- }
- }
-
- @Test
public void testInstanceData() throws Exception {
TestSecurityHelper securityHelper = new TestSecurityHelper("user1");
http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
index a950eb6..116b6ec 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/authorization/AmbariAuthorizationFilterTest.java
@@ -18,23 +18,40 @@
package org.apache.ambari.server.security.authorization;
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.Assert;
+
import org.apache.ambari.server.orm.entities.PermissionEntity;
import org.apache.ambari.server.orm.entities.PrivilegeEntity;
+import org.apache.ambari.server.orm.entities.ViewInstanceEntity.ViewInstanceVersionDTO;
+import org.apache.ambari.server.view.ViewRegistry;
import org.easymock.EasyMock;
-import org.junit.BeforeClass;
+import org.easymock.IAnswer;
import org.junit.Test;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.easymock.EasyMock.*;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import com.google.common.collect.Table.Cell;
public class AmbariAuthorizationFilterTest {
@@ -121,4 +138,235 @@ public class AmbariAuthorizationFilterTest {
verify(request, response, chain, filter, securityContext, authentication, authority,
privilegeEntity, permission, filterConfig);
}
+
+ @Test
+ public void testDoFilter_adminAccess() throws Exception {
+ final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+ urlTests.put("/api/v1/clusters/cluster", "GET", true);
+ urlTests.put("/api/v1/clusters/cluster", "POST", true);
+ urlTests.put("/api/v1/views", "GET", true);
+ urlTests.put("/api/v1/views", "POST", true);
+ urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+ urlTests.put("/api/v1/persist/SomeValue", "POST", true);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", true);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", true);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", true);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", true);
+ urlTests.put("/api/v1/users/user1", "GET", true);
+ urlTests.put("/api/v1/users/user1", "POST", true);
+ urlTests.put("/api/v1/users/user2", "GET", true);
+ urlTests.put("/api/v1/users/user2", "POST", true);
+ urlTests.put("/api/v1/groups", "GET", true);
+ urlTests.put("/api/v1/ldap_sync_events", "GET", true);
+ urlTests.put("/any/other/URL", "GET", true);
+ urlTests.put("/any/other/URL", "POST", true);
+
+ performGeneralDoFilterTest("admin", new int[] {PermissionEntity.AMBARI_ADMIN_PERMISSION}, urlTests);
+ }
+
+ @Test
+ public void testDoFilter_clusterViewerAccess() throws Exception {
+ final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+ urlTests.put("/api/v1/clusters/cluster", "GET", true);
+ urlTests.put("/api/v1/clusters/cluster", "POST", true);
+ urlTests.put("/api/v1/views", "GET", true);
+ urlTests.put("/api/v1/views", "POST", false);
+ urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+ urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+ urlTests.put("/api/v1/users/user1", "GET", true);
+ urlTests.put("/api/v1/users/user1", "POST", true);
+ urlTests.put("/api/v1/users/user2", "GET", false);
+ urlTests.put("/api/v1/users/user2", "POST", false);
+ urlTests.put("/api/v1/groups", "GET", false);
+ urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+ urlTests.put("/any/other/URL", "GET", true);
+ urlTests.put("/any/other/URL", "POST", false);
+
+ performGeneralDoFilterTest("user1", new int[] {PermissionEntity.CLUSTER_READ_PERMISSION}, urlTests);
+ }
+
+ @Test
+ public void testDoFilter_clusterOperatorAccess() throws Exception {
+ final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+ urlTests.put("/api/v1/clusters/cluster", "GET", true);
+ urlTests.put("/api/v1/clusters/cluster", "POST", true);
+ urlTests.put("/api/v1/views", "GET", true);
+ urlTests.put("/api/v1/views", "POST", false);
+ urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+ urlTests.put("/api/v1/persist/SomeValue", "POST", true);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+ urlTests.put("/api/v1/users/user1", "GET", true);
+ urlTests.put("/api/v1/users/user1", "POST", true);
+ urlTests.put("/api/v1/users/user2", "GET", false);
+ urlTests.put("/api/v1/users/user2", "POST", false);
+ urlTests.put("/api/v1/groups", "GET", false);
+ urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+ urlTests.put("/any/other/URL", "GET", true);
+ urlTests.put("/any/other/URL", "POST", false);
+
+ performGeneralDoFilterTest("user1", new int[] {PermissionEntity.CLUSTER_OPERATE_PERMISSION}, urlTests);
+ }
+
+ @Test
+ public void testDoFilter_viewUserAccess() throws Exception {
+ final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+ urlTests.put("/api/v1/clusters/cluster", "GET", true);
+ urlTests.put("/api/v1/clusters/cluster", "POST", false);
+ urlTests.put("/api/v1/views", "GET", true);
+ urlTests.put("/api/v1/views", "POST", true);
+ urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+ urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", true);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", true);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+ urlTests.put("/api/v1/users/user1", "GET", true);
+ urlTests.put("/api/v1/users/user1", "POST", true);
+ urlTests.put("/api/v1/users/user2", "GET", false);
+ urlTests.put("/api/v1/users/user2", "POST", false);
+ urlTests.put("/api/v1/groups", "GET", false);
+ urlTests.put("/api/v1/ldap_sync_events", "GET", false);
+ urlTests.put("/any/other/URL", "GET", true);
+ urlTests.put("/any/other/URL", "POST", false);
+
+ performGeneralDoFilterTest("user1", new int[] {PermissionEntity.VIEW_USE_PERMISSION}, urlTests);
+ }
+
+ @Test
+ public void testDoFilter_userNoPermissionsAccess() throws Exception {
+ final Table<String, String, Boolean> urlTests = HashBasedTable.create();
+ urlTests.put("/api/v1/clusters/cluster", "GET", true);
+ urlTests.put("/api/v1/clusters/cluster", "POST", false);
+ urlTests.put("/api/v1/views", "GET", true);
+ urlTests.put("/api/v1/views", "POST", false);
+ urlTests.put("/api/v1/persist/SomeValue", "GET", true);
+ urlTests.put("/api/v1/persist/SomeValue", "POST", false);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "GET", false);
+ urlTests.put("/views/AllowedView/SomeVersion/SomeInstance", "POST", false);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "GET", false);
+ urlTests.put("/views/DeniedView/AnotherVersion/AnotherInstance", "POST", false);
+ urlTests.put("/api/v1/users/user1", "GET", false);
+ urlTests.put("/api/v1/users/user1", "POST", false);
+ urlTests.put("/api/v1/users/user2", "GET", true);
+ urlTests.put("/api/v1/users/user2", "POST", true);
+ urlTests.put("/any/other/URL", "GET", true);
+ urlTests.put("/any/other/URL", "POST", false);
+
+ performGeneralDoFilterTest("user2", new int[0], urlTests);
+ }
+
+ /**
+ * Creates mocks with given permissions and performs all given url tests.
+ *
+ * @param username user name
+ * @param permissionsGranted array of user permissions
+ * @param urlTests map of triples: url - http method - is allowed
+ * @throws Exception
+ */
+ private void performGeneralDoFilterTest(String username, final int[] permissionsGranted, Table<String, String, Boolean> urlTests) throws Exception {
+ final SecurityContext securityContext = createNiceMock(SecurityContext.class);
+ final Authentication authentication = createNiceMock(Authentication.class);
+ final FilterConfig filterConfig = createNiceMock(FilterConfig.class);
+ final AmbariAuthorizationFilter filter = createMockBuilder(AmbariAuthorizationFilter.class)
+ .addMockedMethod("getSecurityContext").addMockedMethod("getViewRegistry").withConstructor().createMock();
+ final List<AmbariGrantedAuthority> authorities = new ArrayList<AmbariGrantedAuthority>();
+ final ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class);
+
+ for (int permissionGranted: permissionsGranted) {
+ final AmbariGrantedAuthority authority = createNiceMock(AmbariGrantedAuthority.class);
+ final PrivilegeEntity privilegeEntity = createNiceMock(PrivilegeEntity.class);
+ final PermissionEntity permission = createNiceMock(PermissionEntity.class);
+
+ expect(authority.getPrivilegeEntity()).andReturn(privilegeEntity).anyTimes();
+ expect(privilegeEntity.getPermission()).andReturn(permission).anyTimes();
+ expect(permission.getId()).andReturn(permissionGranted).anyTimes();
+
+ replay(authority, privilegeEntity, permission);
+ authorities.add(authority);
+ }
+
+ EasyMock.<Collection<? extends GrantedAuthority>>expect(authentication.getAuthorities()).andReturn(authorities).anyTimes();
+ expect(filterConfig.getInitParameter("realm")).andReturn("AuthFilter").anyTimes();
+ expect(authentication.isAuthenticated()).andReturn(true).anyTimes();
+ expect(authentication.getName()).andReturn(username).anyTimes();
+ expect(filter.getSecurityContext()).andReturn(securityContext).anyTimes();
+ expect(filter.getViewRegistry()).andReturn(viewRegistry).anyTimes();
+ expect(securityContext.getAuthentication()).andReturn(authentication).anyTimes();
+ expect(viewRegistry.checkPermission(EasyMock.eq("AllowedView"), EasyMock.<String>anyObject(), EasyMock.<String>anyObject(), EasyMock.anyBoolean())).andAnswer(new IAnswer<Boolean>() {
+ @Override
+ public Boolean answer() throws Throwable {
+ for (int permissionGranted: permissionsGranted) {
+ if (permissionGranted == PermissionEntity.VIEW_USE_PERMISSION) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }).anyTimes();
+ expect(viewRegistry.checkPermission(EasyMock.eq("DeniedView"), EasyMock.<String>anyObject(), EasyMock.<String>anyObject(), EasyMock.anyBoolean())).andReturn(false).anyTimes();
+
+ replay(authentication, filterConfig, filter, securityContext, viewRegistry);
+
+ for (final Cell<String, String, Boolean> urlTest: urlTests.cellSet()) {
+ final FilterChain chain = EasyMock.createStrictMock(FilterChain.class);
+ final HttpServletRequest request = createNiceMock(HttpServletRequest.class);
+ final HttpServletResponse response = createNiceMock(HttpServletResponse.class);
+
+ expect(request.getRequestURI()).andReturn(urlTest.getRowKey()).anyTimes();
+ expect(request.getMethod()).andReturn(urlTest.getColumnKey()).anyTimes();
+ if (urlTest.getValue()) {
+ chain.doFilter(EasyMock.<ServletRequest>anyObject(), EasyMock.<ServletResponse>anyObject());
+ EasyMock.expectLastCall().once();
+ }
+
+ replay(request, response, chain);
+
+ try {
+ filter.doFilter(request, response, chain);
+ } catch (AssertionError error) {
+ throw new Exception("doFilter() should not be chained on " + urlTest.getColumnKey() + " " + urlTest.getRowKey(), error);
+ }
+
+ try {
+ verify(chain);
+ } catch (AssertionError error) {
+ throw new Exception("verify( failed on " + urlTest.getColumnKey() + " " + urlTest.getRowKey(), error);
+ }
+ }
+ }
+
+ @Test
+ public void testParseUserName() throws Exception {
+ final String[] pathesToTest = {
+ "/api/v1/users/user",
+ "/api/v1/users/user?fields=*",
+ "/api/v22/users/user?fields=*"
+ };
+ for (String contextPath: pathesToTest) {
+ final String username = AmbariAuthorizationFilter.parseUserName(contextPath);
+ Assert.assertEquals("user", username);
+ }
+ }
+
+ @Test
+ public void testParseViewContextPath() throws Exception {
+ final String[] pathesToTest = {
+ AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1",
+ AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/index.html",
+ AmbariAuthorizationFilter.VIEWS_CONTEXT_PATH_PREFIX + "MY_VIEW/1.0.0/INSTANCE1/api/test"
+ };
+ for (String contextPath: pathesToTest) {
+ final ViewInstanceVersionDTO dto = AmbariAuthorizationFilter.parseViewInstanceInfo(contextPath);
+ Assert.assertEquals("INSTANCE1", dto.getInstanceName());
+ Assert.assertEquals("MY_VIEW", dto.getViewName());
+ Assert.assertEquals("1.0.0", dto.getVersion());
+ }
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/f92ad8f5/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 5487db8..dbdb469 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
@@ -313,4 +313,5 @@ public class TestUsers {
userDAO.merge(ldapUser);
}
+
}