You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2015/12/17 06:45:00 UTC

[2/2] ambari git commit: AMBARI-14391. Add a test to verify Role Based Access Control for a non-admin user (Nahappan Somasundaram via smohanty)

AMBARI-14391. Add a test to verify Role Based Access Control for a non-admin user (Nahappan Somasundaram via smohanty)


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

Branch: refs/heads/trunk
Commit: f2e797abd9ce6db53995085c6693ed16d278f185
Parents: 4fb0f6e
Author: Sumit Mohanty <sm...@hortonworks.com>
Authored: Wed Dec 16 21:42:42 2015 -0800
Committer: Sumit Mohanty <sm...@hortonworks.com>
Committed: Wed Dec 16 21:42:42 2015 -0800

----------------------------------------------------------------------
 .../java/org/apache/ambari/funtest/AppTest.java |   55 -
 .../ambari/funtest/server/AmbariUserRole.java   |   68 +
 .../funtest/server/LocalAmbariServer.java       |    7 -
 .../api/cluster/DeleteClusterWebRequest.java    |   60 +
 .../api/cluster/SetUserPrivilegeWebRequest.java |   96 ++
 .../server/api/user/CreateUserWebRequest.java   |   95 ++
 .../server/api/user/DeleteUserWebRequest.java   |   56 +
 .../funtest/server/tests/DeleteServiceTest.java |   12 +-
 .../funtest/server/tests/GetStacksTest.java     |  102 ++
 .../funtest/server/tests/LocalAmbariServer.java |   99 --
 .../tests/RoleBasedAccessControlBasicTest.java  |  249 +++
 .../funtest/server/tests/ServerTestBase.java    |  169 +-
 .../server/tests/StartStopServerTest.java       |  104 --
 .../funtest/server/utils/ClusterUtils.java      |  128 +-
 .../src/test/resources/log4j.properties         |    4 +-
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  | 1533 ++++++++++++++++++
 16 files changed, 2521 insertions(+), 316 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/AppTest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/AppTest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/AppTest.java
deleted file mode 100644
index e7fd76f..0000000
--- a/ambari-funtest/src/test/java/org/apache/ambari/funtest/AppTest.java
+++ /dev/null
@@ -1,55 +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.funtest;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest 
-    extends TestCase
-{
-    /**
-     * Create the test case
-     *
-     * @param testName name of the test case
-     */
-    public AppTest( String testName )
-    {
-        super( testName );
-    }
-
-    /**
-     * @return the suite of tests being tested
-     */
-    public static Test suite()
-    {
-        return new TestSuite( AppTest.class );
-    }
-
-    /**
-     * Rigourous Test :-)
-     */
-    public void testApp()
-    {
-        assertTrue( true );
-    }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/AmbariUserRole.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/AmbariUserRole.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/AmbariUserRole.java
new file mode 100644
index 0000000..b5d8b34
--- /dev/null
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/AmbariUserRole.java
@@ -0,0 +1,68 @@
+/*
+ * 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.funtest.server;
+
+/**
+ * Ambari role-based access controls
+ */
+public enum AmbariUserRole {
+    NONE,
+
+    CLUSTER_USER {
+        @Override
+        public String toString() {
+            return "CLUSTER.USER";
+        }
+    },
+
+    SERVICE_OPERATOR {
+        @Override
+        public String toString() {
+            return "SERVICE.OPERATOR";
+        }
+    },
+
+    SERVICE_ADMINISTRATOR {
+        @Override
+        public String toString() {
+            return "SERVICE.ADMINISTRATOR";
+        }
+    },
+
+    CLUSTER_OPERATOR {
+        @Override
+        public String toString() {
+            return "CLUSTER.OPERATOR";
+        }
+    },
+
+    CLUSTER_ADMINISTRATOR {
+        @Override
+        public String toString() {
+            return "CLUSTER.ADMINISTRATOR";
+        }
+    },
+
+    AMBARI_ADMINISTRATOR {
+        @Override
+        public String toString() {
+            return "AMBARI.ADMINISTRATOR";
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/LocalAmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/LocalAmbariServer.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/LocalAmbariServer.java
index 3698027..31f0ee1 100644
--- a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/LocalAmbariServer.java
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/LocalAmbariServer.java
@@ -19,9 +19,7 @@
 package org.apache.ambari.funtest.server;
 
 import com.google.inject.Inject;
-import com.google.inject.persist.PersistService;
 import org.apache.ambari.server.controller.AmbariServer;
-import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import com.google.inject.Injector;
@@ -68,7 +66,6 @@ public class LocalAmbariServer implements Runnable {
       LOG.info("Attempting to start ambari server...");
 
       AmbariServer.setupProxyAuth();
-      injector.getInstance(GuiceJpaInitializer.class);
       ambariServer = injector.getInstance(AmbariServer.class);
       ambariServer.initViewRegistry();
       ambariServer.run();
@@ -91,9 +88,5 @@ public class LocalAmbariServer implements Runnable {
     if (ambariServer != null) {
       ambariServer.stop();
     }
-
-    if (injector != null) {
-        injector.getInstance(PersistService.class).stop();
-    }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/DeleteClusterWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/DeleteClusterWebRequest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/DeleteClusterWebRequest.java
new file mode 100644
index 0000000..a5530f1
--- /dev/null
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/DeleteClusterWebRequest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.funtest.server.api.cluster;
+
+import org.apache.ambari.funtest.server.AmbariHttpWebRequest;
+import org.apache.ambari.funtest.server.ConnectionParams;
+
+/**
+ * Deletes the specified cluster.
+ */
+public class DeleteClusterWebRequest extends AmbariHttpWebRequest {
+    private final String clusterName;
+    private static String pathFormat = "/api/v1/clusters/%s";
+
+    /**
+     * Deletes a cluster
+     *
+     * @param params - Ambari server connection information
+     * @param clusterName - Cluster to be deleted.
+     */
+    public DeleteClusterWebRequest(ConnectionParams params, String clusterName) {
+        super(params);
+        this.clusterName = clusterName;
+    }
+
+    public String getClusterName() {
+        return this.clusterName;
+    }
+
+    @Override
+    public String getHttpMethod() {
+        return "DELETE";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/SetUserPrivilegeWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/SetUserPrivilegeWebRequest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/SetUserPrivilegeWebRequest.java
new file mode 100644
index 0000000..0cc749b
--- /dev/null
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/cluster/SetUserPrivilegeWebRequest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.funtest.server.api.cluster;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.funtest.server.AmbariHttpWebRequest;
+import org.apache.ambari.funtest.server.AmbariUserRole;
+import org.apache.ambari.funtest.server.ConnectionParams;
+
+/**
+ * Adds an existing configuration, identified by it's type and tag, to a cluster.
+ */
+public class SetUserPrivilegeWebRequest extends AmbariHttpWebRequest {
+    private final String clusterName;
+    private final String userName;
+    private final String principalType;
+    private final AmbariUserRole userRole;
+    private static String pathFormat = "/api/v1/clusters/%s/privileges";
+
+    /**
+     *
+     * @param serverParams - Ambari server connection information
+     * @param clusterName
+     * @param userName
+     * @param userRole
+     * @param principalType - USER or GROUP. Use PrincipalTypeEntity.USER_PRINCIPAL_TYPE_NAME or
+     *                      PrincipalTypeEntity.GROUP_PRINCIPAL_TYPE_NAME
+     */
+    public SetUserPrivilegeWebRequest(ConnectionParams serverParams, String clusterName, String userName,
+                                      AmbariUserRole userRole, String principalType) {
+
+        super(serverParams);
+        this.clusterName = clusterName;
+        this.userName = userName;
+        this.principalType = principalType;
+        this.userRole = userRole;
+    }
+
+    /**
+     * Gets the REST API method.
+     *
+     * @return - PUT.
+     */
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, clusterName);
+    }
+
+    /**
+     * Gets the request data.
+     *
+     * @return - Request data.
+     */
+    @Override
+    protected String getRequestData() {
+        /**
+         * { "PrivilegeInfo" : {"permission_name": userRole, "principal_name": userName, "principal_type": principalType}}
+         */
+        JsonObject jsonObject;
+        JsonObject jsonPrivilegeInfo = new JsonObject();
+
+        jsonPrivilegeInfo.addProperty("permission_name", userRole.toString());
+        jsonPrivilegeInfo.addProperty("principal_name", userName);
+        jsonPrivilegeInfo.addProperty("principal_type", principalType);
+        jsonObject = createJsonObject("PrivilegeInfo", jsonPrivilegeInfo);
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/CreateUserWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/CreateUserWebRequest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/CreateUserWebRequest.java
new file mode 100644
index 0000000..c0b4cab
--- /dev/null
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/CreateUserWebRequest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.funtest.server.api.user;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.apache.ambari.funtest.server.AmbariHttpWebRequest;
+import org.apache.ambari.funtest.server.ConnectionParams;
+
+/**
+ * Creates a new user.
+ */
+public class CreateUserWebRequest extends AmbariHttpWebRequest {
+    private final String userName;
+    private final String password;
+    private final boolean isActive;
+    private final boolean isAdmin;
+    private static String pathFormat = "/api/v1/users/%s";
+
+    public enum ActiveUser {
+        FALSE,
+        TRUE
+    }
+
+    public enum AdminUser {
+        FALSE,
+        TRUE
+    }
+
+    /**
+     * Adds the specified service component to the specified service.
+     *
+     * @param params - Ambari server connection information.
+     * @param userName - User name.
+     * @param password - Password in clear text.
+     * @param activeUser - Specifies whether the user is active or not.
+     * @param adminUser - Specifies whether the user is an administrator or not.
+     */
+    public CreateUserWebRequest(ConnectionParams params, String userName, String password,
+                             ActiveUser activeUser, AdminUser adminUser) {
+        super(params);
+        this.userName = userName;
+        this.password = password;
+        this.isActive = (activeUser == ActiveUser.TRUE);
+        this.isAdmin = (adminUser == AdminUser.TRUE);
+    }
+
+    @Override
+    public String getHttpMethod() {
+        return "POST";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, userName);
+    }
+
+    @Override
+    protected String getRequestData() {
+        /**
+         * { "Users" : {"active": true/false, "admin": true/false, "password": password } }
+         */
+        JsonObject jsonObject;
+        JsonObject jsonUserInfo = new JsonObject();
+
+        jsonUserInfo.addProperty("active", isActive);
+        jsonUserInfo.addProperty("admin", isAdmin);
+        jsonUserInfo.addProperty("password", password);
+
+        jsonObject = createJsonObject("Users", jsonUserInfo);
+        Gson gson = new Gson();
+        return gson.toJson(jsonObject);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/DeleteUserWebRequest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/DeleteUserWebRequest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/DeleteUserWebRequest.java
new file mode 100644
index 0000000..755119a
--- /dev/null
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/api/user/DeleteUserWebRequest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.funtest.server.api.user;
+
+import org.apache.ambari.funtest.server.AmbariHttpWebRequest;
+import org.apache.ambari.funtest.server.ConnectionParams;
+
+/**
+ * Deletes the specified user.
+ */
+public class DeleteUserWebRequest extends AmbariHttpWebRequest {
+    private final String userName;
+    private static String pathFormat = "/api/v1/users/%s";
+
+    /**
+     * Deletes a user
+     *
+     * @param params - Ambari server connection information
+     * @param userName - User to be deleted.
+     */
+    public DeleteUserWebRequest(ConnectionParams params, String userName) {
+        super(params);
+        this.userName = userName;
+    }
+
+    @Override
+    public String getHttpMethod() {
+        return "DELETE";
+    }
+
+    /**
+     * Get REST API path fragment for construction full URI.
+     *
+     * @return - REST API path
+     */
+    @Override
+    protected String getApiPath() {
+        return String.format(pathFormat, userName);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/DeleteServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/DeleteServiceTest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/DeleteServiceTest.java
index 3f38acf..472bdc4 100644
--- a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/DeleteServiceTest.java
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/DeleteServiceTest.java
@@ -22,6 +22,7 @@ import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import org.apache.ambari.funtest.server.ConnectionParams;
 import org.apache.ambari.funtest.server.WebResponse;
+import org.apache.ambari.funtest.server.api.cluster.DeleteClusterWebRequest;
 import org.apache.ambari.funtest.server.api.service.DeleteServiceWebRequest;
 import org.apache.ambari.funtest.server.api.service.GetServiceWebRequest;
 import org.apache.ambari.funtest.server.api.service.StopServiceWebRequest;
@@ -43,7 +44,8 @@ import org.apache.ambari.server.state.State;
 
 import org.apache.commons.httpclient.HttpStatus;
 
-import org.junit.Ignore;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.junit.Test;
 
 import java.util.List;
@@ -56,8 +58,10 @@ import static org.junit.Assert.assertTrue;
  * Simple test that starts the local ambari server,
  * tests it's status and shuts down the server.
  */
-@Ignore
 public class DeleteServiceTest extends ServerTestBase {
+
+    private static Log LOG = LogFactory.getLog(DeleteServiceTest.class);
+
     /**
      * Set up a test cluster with a service, a host and a few components.
      * Attempt to delete the service. Verify the state of the DB.
@@ -193,5 +197,9 @@ public class DeleteServiceTest extends ServerTestBase {
          */
         hostComponentDesiredStateEntities = hostComponentDesiredStateDAO.findAll();
         assertEquals(hostComponentDesiredStateEntities.size(), 0);
+
+        jsonResponse = RestApiUtils.executeRequest(new DeleteClusterWebRequest(params, clusterName));
+
+        LOG.info(jsonResponse);
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/GetStacksTest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/GetStacksTest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/GetStacksTest.java
new file mode 100644
index 0000000..4f316b5
--- /dev/null
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/GetStacksTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.funtest.server.tests;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
+
+import java.io.StringReader;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonArray;
+
+import java.io.IOException;
+
+import org.apache.http.HttpStatus;
+
+/**
+ * Simple test to get the list of stacks. Does not touch the DB.
+ */
+public class GetStacksTest extends ServerTestBase {
+  /**
+   * Waits for the ambari server to startup and then checks it's
+   * status by querying /api/v1/stacks (does not touch the DB)
+   */
+  @Test
+  public void testServerStatus() throws IOException {
+    /**
+     * Query the ambari server for the list of stacks.
+     * A successful GET returns the list of stacks.
+     * We should get a json like:
+     * {
+     *   "href" : "http://localhost:9995/api/v1/stacks",
+     *   "items" : [
+     *   {
+     *     "href" : "http://localhost:9995/api/v1/stacks/HDP",
+     *     "Stacks" : {
+     *     "stack_name" : "HDP"
+     *     }
+     *   }
+     *  ]
+     * }
+     */
+
+    /**
+     * Test URL for GETting the status of the ambari server
+     */
+    String stacksPath = "/api/v1/stacks";
+    String stacksUrl = String.format(SERVER_URL_FORMAT, serverPort) + stacksPath;
+    HttpClient httpClient = new HttpClient();
+    GetMethod getMethod = new GetMethod(stacksUrl);
+
+    try {
+      getMethod.addRequestHeader("Authorization", getBasicAdminAuthentication());
+      getMethod.addRequestHeader("X-Requested-By", "ambari");
+      int statusCode = httpClient.executeMethod(getMethod);
+
+      assertEquals(HttpStatus.SC_OK, statusCode); // HTTP status code 200
+
+      String responseBody = getMethod.getResponseBodyAsString();
+
+      assertTrue(responseBody != null); // Make sure response body is valid
+
+      JsonElement jsonElement = new JsonParser().parse(new JsonReader(new StringReader(responseBody)));
+
+      assertTrue (jsonElement != null); // Response was a JSON string
+
+      JsonObject jsonObject = jsonElement.getAsJsonObject();
+
+      assertTrue (jsonObject.has("items"));  // Should have "items" entry
+
+      JsonArray stacksArray = jsonObject.get("items").getAsJsonArray();
+
+      assertTrue (stacksArray.size() > 0); // Should have at least one stack
+
+    } finally {
+      getMethod.releaseConnection();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/LocalAmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/LocalAmbariServer.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/LocalAmbariServer.java
deleted file mode 100644
index 24b4ccf..0000000
--- a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/LocalAmbariServer.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.functionaltests.server;
-
-import com.google.inject.Inject;
-import com.google.inject.persist.PersistService;
-import org.apache.ambari.server.controller.AmbariServer;
-import org.apache.ambari.server.orm.GuiceJpaInitializer;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import com.google.inject.Injector;
-
-/**
-* Wrap AmbariServer as a testable unit.
-*/
-public class LocalAmbariServer implements Runnable {
-
-  private static Log LOG = LogFactory.getLog(AmbariServer.class);
-
-  /**
-   * Actual ambari server instance.
-   */
-  private AmbariServer ambariServer = null;
-
-  @Inject
-  private Injector injector;
-
-  public LocalAmbariServer() {}
-
-  /**
-   * Thread entry point.
-   */
-  @Override
-  public void run(){
-    try {
-      startServer();
-    }
-    catch (Exception ex) {
-      LOG.info("Exception received ", ex);
-      throw new RuntimeException(ex);
-    }
-  }
-
-  /**
-   * Configures the Guice injector to use the in-memory test DB
-   * and attempts to start an instance of AmbariServer.
-   *
-   * @throws Exception
-   */
-  private void startServer() throws Exception {
-    try {
-      LOG.info("Attempting to start ambari server...");
-
-      AmbariServer.setupProxyAuth();
-      injector.getInstance(GuiceJpaInitializer.class);
-      ambariServer = injector.getInstance(AmbariServer.class);
-      ambariServer.initViewRegistry();
-      ambariServer.run();
-    } catch (InterruptedException ex) {
-      LOG.info(ex);
-    } catch (Throwable t) {
-      LOG.error("Failed to run the Ambari Server", t);
-      stopServer();
-      throw t;
-    }
-  }
-
-  /**
-   * Attempts to stop the test AmbariServer instance.
-   * @throws Exception
-   */
-  public void stopServer() throws Exception {
-    LOG.info("Stopping ambari server...");
-
-    if (ambariServer != null) {
-      ambariServer.stop();
-    }
-
-    if (injector != null) {
-        injector.getInstance(PersistService.class).stop();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/RoleBasedAccessControlBasicTest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/RoleBasedAccessControlBasicTest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/RoleBasedAccessControlBasicTest.java
new file mode 100644
index 0000000..947cfd0
--- /dev/null
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/RoleBasedAccessControlBasicTest.java
@@ -0,0 +1,249 @@
+/*
+ * 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.funtest.server.tests;
+
+
+import com.google.gson.JsonElement;
+import org.apache.ambari.funtest.server.AmbariUserRole;
+import org.apache.ambari.funtest.server.ClusterConfigParams;
+import org.apache.ambari.funtest.server.ConnectionParams;
+import org.apache.ambari.funtest.server.WebRequest;
+import org.apache.ambari.funtest.server.WebResponse;
+import org.apache.ambari.funtest.server.api.cluster.CreateClusterWebRequest;
+import org.apache.ambari.funtest.server.api.cluster.CreateConfigurationWebRequest;
+import org.apache.ambari.funtest.server.api.cluster.DeleteClusterWebRequest;
+import org.apache.ambari.funtest.server.api.cluster.GetAllClustersWebRequest;
+import org.apache.ambari.funtest.server.api.user.DeleteUserWebRequest;
+import org.apache.ambari.funtest.server.utils.ClusterUtils;
+import org.apache.ambari.funtest.server.utils.RestApiUtils;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests operations with users with different levels of privileges
+ */
+public class RoleBasedAccessControlBasicTest extends ServerTestBase {
+
+    private String clusterName = "c1";
+    private String hostName = "host1";
+    private String clusterVersion = "HDP-2.2.0";
+
+    private static Log LOG = LogFactory.getLog(RoleBasedAccessControlBasicTest.class);
+
+    @Override
+    public void setup() throws Exception {
+        super.setup();
+        setupCluster();
+    }
+
+    @Override
+    public void teardown() throws Exception {
+        teardownCluster();
+        super.teardown();
+    }
+
+    /**
+     * Creates an anonymous user (user with no role). Attempts to get the list of clusters
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testGetClustersAsAnonUser() throws Exception {
+        JsonElement jsonResponse;
+        ConnectionParams adminConnectionParams = createAdminConnectionParams();
+        String anonUserName = "nothing";
+        String anonUserPwd = "nothing";
+
+        /**
+         * Create a new user (non-admin)
+         */
+        ClusterUtils.createUser(adminConnectionParams, clusterName, anonUserName, anonUserPwd, AmbariUserRole.NONE);
+
+        /**
+         * Attempt to query all the clusters using this user's privilege. Right now we should be
+         * able to get the list of clusters, though this user should not be able to. But this is
+         * required for UI to display the clusters.
+         *
+         * todo: Fix this when UI is fixed.
+         */
+        ConnectionParams anonUserParams = createConnectionParams(anonUserName, anonUserPwd);
+        jsonResponse = RestApiUtils.executeRequest(new GetAllClustersWebRequest(anonUserParams));
+
+        assertFalse(jsonResponse.isJsonNull());
+
+        /**
+         * Delete the user
+         */
+        jsonResponse = RestApiUtils.executeRequest(new DeleteUserWebRequest(adminConnectionParams, anonUserName));
+        LOG.info(jsonResponse);
+    }
+
+    /**
+     * Creates an anonymous user and uses the user to add a cluster configuration.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testAddClusterConfigAsAnonUser() throws Exception {
+        ConnectionParams adminConnectionParams = createAdminConnectionParams();
+        String anonUserName = "nothing";
+        String anonUserPwd = "nothing";
+
+        /**
+         * Create a new user (non-admin)
+         */
+        ClusterUtils.createUser(adminConnectionParams, clusterName, anonUserName, anonUserPwd, AmbariUserRole.NONE);
+
+        /**
+         * Create and add a configuration to our cluster using the new user's privilege
+         */
+
+        String configType = "test-hadoop-env";
+        String configTag = "version1";
+        ClusterConfigParams configParams = new ClusterConfigParams();
+        configParams.setClusterName(clusterName);
+        configParams.setConfigType(configType);
+        configParams.setConfigTag(configTag);
+        configParams.setProperties(new HashMap<String, String>() {{
+            put("fs.default.name", "localhost:9995");
+        }});
+
+        /**
+         * Attempting to create the configuration should fail with 403
+         */
+        ConnectionParams anonUserParams = createConnectionParams(anonUserName, anonUserPwd);
+        WebRequest webRequest = new CreateConfigurationWebRequest(anonUserParams, configParams);
+        WebResponse webResponse = webRequest.getResponse();
+        assertEquals(HttpStatus.SC_FORBIDDEN, webResponse.getStatusCode());
+
+        /**
+         * Delete the user
+         */
+        JsonElement jsonResponse = RestApiUtils.executeRequest(new DeleteUserWebRequest(adminConnectionParams, "nothing"));
+        LOG.info(jsonResponse);
+    }
+
+    /**
+     * Creates a user with cluster administrator privilege and adds a cluster configuration.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testAddClusterConfigAsClusterAdmin() throws Exception {
+        ConnectionParams adminConnectionParams = createAdminConnectionParams();
+
+        String clusterAdminName = "clusterAdmin";
+        String clusterAdminPwd = "clusterAdmin";
+
+        /**
+         * Create a user with cluster admin role
+         */
+        ClusterUtils.createUserClusterAdministrator(adminConnectionParams, clusterName,
+                clusterAdminName, clusterAdminPwd);
+
+        /**
+         * Create and add a configuration to our cluster using the new user's privilege
+         */
+
+        String configType = "test-hadoop-env";
+        String configTag = "version1";
+        ClusterConfigParams configParams = new ClusterConfigParams();
+        configParams.setClusterName(clusterName);
+        configParams.setConfigType(configType);
+        configParams.setConfigTag(configTag);
+        configParams.setProperties(new HashMap<String, String>() {{
+            put("fs.default.name", "localhost:9995");
+        }});
+
+        /**
+         * This user has enough privilege to create the cluster configuration. Should succeed with 201.
+         */
+        ConnectionParams userConnectionParams = createConnectionParams(clusterAdminName, clusterAdminPwd);
+        WebRequest webRequest = new CreateConfigurationWebRequest(userConnectionParams, configParams);
+        WebResponse webResponse = webRequest.getResponse();
+        assertEquals(HttpStatus.SC_CREATED, webResponse.getStatusCode());
+
+        /**
+         * Delete the user
+         */
+        RestApiUtils.executeRequest(new DeleteUserWebRequest(adminConnectionParams, clusterAdminName));
+    }
+
+    /**
+     * Create a cluster with name "c1". Does not have any hosts.
+     *
+     * @throws Exception
+     */
+    private void setupCluster() throws Exception {
+        JsonElement jsonResponse;
+        ConnectionParams params = createAdminConnectionParams();
+
+        /**
+         * Create a cluster as admin:admin
+         */
+        jsonResponse = RestApiUtils.executeRequest(new CreateClusterWebRequest(params, clusterName, clusterVersion));
+
+        LOG.info(jsonResponse);
+    }
+
+    private void teardownCluster() throws Exception {
+        JsonElement jsonResponse;
+        ConnectionParams params = createAdminConnectionParams();
+
+        jsonResponse = RestApiUtils.executeRequest(new DeleteClusterWebRequest(params, clusterName));
+
+        LOG.info(jsonResponse);
+    }
+
+    /**
+     * Helper method to create administrator connection parameters to the server.
+     *
+     * @return
+     */
+    private ConnectionParams createAdminConnectionParams() {
+        return createConnectionParams(getAdminUserName(), getAdminPassword());
+    }
+
+    /**
+     * Helper method to create connection parameters to the server based on the
+     * specified user credentials.
+     *
+     * @param userName
+     * @param password
+     * @return
+     */
+    private ConnectionParams createConnectionParams(String userName, String password) {
+        ConnectionParams params = new ConnectionParams();
+
+        params.setServerName("localhost");
+        params.setServerApiPort(serverPort);
+        params.setServerAgentPort(serverAgentPort);
+        params.setUserName(userName);
+        params.setPassword(password);
+
+        return params;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/ServerTestBase.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/ServerTestBase.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/ServerTestBase.java
index b915977..7b9600f 100644
--- a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/ServerTestBase.java
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/ServerTestBase.java
@@ -20,32 +20,43 @@ package org.apache.ambari.funtest.server.tests;
 
 import com.google.inject.Guice;
 import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
 import org.apache.ambari.funtest.server.LocalAmbariServer;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.funtest.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.controller.ControllerModule;
+import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.BeforeClass;
 
+import java.io.File;
 import java.io.IOException;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.SQLNonTransientConnectionException;
 import java.util.Properties;
 
 /**
  * Base test infrastructure.
  */
 public class ServerTestBase {
+    private static Log LOG = LogFactory.getLog(ServerTestBase.class);
+
     /**
      * Run the ambari server on a thread.
      */
-    protected Thread serverThread = null;
+    protected static Thread serverThread = null;
 
     /**
      * Instance of the local ambari server, which wraps the actual
      * ambari server with test configuration.
      */
-    protected LocalAmbariServer server = null;
+    protected static LocalAmbariServer server = null;
 
     /**
      * Server port
@@ -60,7 +71,7 @@ public class ServerTestBase {
     /**
      * Guice injector using an in-memory DB.
      */
-    protected Injector injector = null;
+    protected static Injector injector = null;
 
     /**
      * Server URL
@@ -68,36 +79,55 @@ public class ServerTestBase {
     protected static String SERVER_URL_FORMAT = "http://localhost:%d";
 
     /**
-     * Start our local server on a thread so that it does not block.
-     *
+     * Initialize the AmbariServer and database once for the entire
+     * duration of the tests since AmbariServer is a singleton.
+     */
+    private static boolean isInitialized;
+
+    /**
+     * Create and populate the DB. Start the AmbariServer.
      * @throws Exception
      */
-    @Before
-    public void setup() throws Exception {
-        InMemoryDefaultTestModule testModule = new InMemoryDefaultTestModule();
-        Properties properties = testModule.getProperties();
-        properties.setProperty(Configuration.AGENT_USE_SSL, "false");
-        properties.setProperty(Configuration.CLIENT_API_PORT_KEY, Integer.toString(serverPort));
-        properties.setProperty(Configuration.SRVR_ONE_WAY_SSL_PORT_KEY, Integer.toString(serverAgentPort));
-        String tmpDir = System.getProperty("java.io.tmpdir");
-        testModule.getProperties().setProperty(Configuration.SRVR_KSTR_DIR_KEY, tmpDir);
-        injector = Guice.createInjector(testModule);
-        server = injector.getInstance(LocalAmbariServer.class);
-        serverThread = new Thread(server);
-        serverThread.start();
-        waitForServer();
-    }
+    @BeforeClass
+    public static void setupTest() throws Exception {
+        if (!isInitialized) {
+            Properties properties = new Properties();
+            properties.setProperty(Configuration.SERVER_PERSISTENCE_TYPE_KEY, "remote");
+            properties.setProperty(Configuration.SERVER_JDBC_URL_KEY, Configuration.JDBC_IN_MEMORY_URL);
+            properties.setProperty(Configuration.SERVER_JDBC_DRIVER_KEY, Configuration.JDBC_IN_MEMROY_DRIVER);
+            properties.setProperty(Configuration.METADATA_DIR_PATH, "src/test/resources/stacks");
+            properties.setProperty(Configuration.SERVER_VERSION_FILE, "src/test/resources/version");
+            properties.setProperty(Configuration.OS_VERSION_KEY, "centos6");
+            properties.setProperty(Configuration.SHARED_RESOURCES_DIR_KEY, "src/test/resources/");
 
-    private String getUserName() {
-        return "admin";
-    }
+            properties.setProperty(Configuration.AGENT_USE_SSL, "false");
+            properties.setProperty(Configuration.CLIENT_API_PORT_KEY, Integer.toString(serverPort));
+            properties.setProperty(Configuration.SRVR_ONE_WAY_SSL_PORT_KEY, Integer.toString(serverAgentPort));
+            String tmpDir = System.getProperty("java.io.tmpdir");
+            properties.setProperty(Configuration.SRVR_KSTR_DIR_KEY, tmpDir);
 
-    private String getPassword() {
-        return "admin";
+            ControllerModule testModule = new ControllerModule(properties);
+
+            injector = Guice.createInjector(testModule);
+            injector.getInstance(PersistService.class).start();
+            initDB();
+
+            server = injector.getInstance(LocalAmbariServer.class);
+            serverThread = new Thread(server);
+            serverThread.start();
+            waitForServer();
+
+            isInitialized = true;
+        }
     }
 
-    protected String getBasicAuthentication() {
-        String authString = getUserName() + ":" + getPassword();
+    /**
+     * Creates the basic authentication string for admin:admin
+     *
+     * @return
+     */
+    protected static String getBasicAdminAuthentication() {
+        String authString = getAdminUserName() + ":" + getAdminPassword();
         byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
         String authStringEnc = new String(authEncBytes);
 
@@ -105,11 +135,70 @@ public class ServerTestBase {
     }
 
     /**
+     * Creates the DB and populates it.
+     *
+     * @throws IOException
+     * @throws SQLException
+     */
+    protected static void initDB() throws IOException, SQLException {
+        createSourceDatabase();
+    }
+
+    /**
+     * Drops the Derby DB.
+     *
+     * @throws ClassNotFoundException
+     * @throws SQLException
+     */
+    protected static void dropDatabase() throws ClassNotFoundException, SQLException {
+        String DROP_DERBY_URL = "jdbc:derby:memory:myDB/ambari;drop=true";
+        Class.forName(Configuration.JDBC_IN_MEMROY_DRIVER);
+        try {
+            DriverManager.getConnection(DROP_DERBY_URL);
+        } catch (SQLNonTransientConnectionException ignored) {
+            LOG.info("Database dropped ", ignored); //error 08006 expected
+        }
+    }
+
+    /**
+     * Executes Ambari-DDL-Derby-CREATE.sql
+     *
+     * @throws IOException
+     * @throws SQLException
+     */
+    private static void createSourceDatabase() throws IOException, SQLException {
+        //create database
+        File projectDir = new File(System.getProperty("user.dir"));
+        File ddlFile = new File(projectDir.getParentFile(), "ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql");
+        String ddlFilename = ddlFile.getPath();
+        DBAccessor dbAccessor = injector.getInstance(DBAccessor.class);
+        dbAccessor.executeScript(ddlFilename);
+    }
+
+    /**
+     * Gets the default administration user name
+     *
+     * @return
+     */
+    protected static String getAdminUserName() {
+        return "admin";
+    }
+
+    /**
+     * Gets the default administrator password
+     *
+     * @return
+     */
+    protected static String getAdminPassword() {
+        return "admin";
+    }
+
+    /**
      * Waits for the local server until it is ready to accept requests.
      *
      * @throws Exception
      */
-    private void waitForServer() throws Exception {
+    private static void waitForServer() throws Exception {
         int count = 1;
 
         while (!isServerUp()) {
@@ -126,7 +215,7 @@ public class ServerTestBase {
      * @return - True if the local server is responsive to queries.
      *           False, otherwise.
      */
-    private boolean isServerUp() {
+    private static boolean isServerUp() {
         String apiPath = "/api/v1/stacks";
 
         String apiUrl = String.format(SERVER_URL_FORMAT, serverPort) + apiPath;
@@ -134,7 +223,7 @@ public class ServerTestBase {
         GetMethod getMethod = new GetMethod(apiUrl);
 
         try {
-            getMethod.addRequestHeader("Authorization", getBasicAuthentication());
+            getMethod.addRequestHeader("Authorization", getBasicAdminAuthentication());
             getMethod.addRequestHeader("X-Requested-By", "ambari");
             int statusCode = httpClient.executeMethod(getMethod);
             String response = getMethod.getResponseBodyAsString();
@@ -150,17 +239,21 @@ public class ServerTestBase {
     }
 
     /**
-     * Shut down the local server.
+     * Perform common initialization for each test case.
+     *
+     * @throws Exception
+     */
+    @Before
+    public void setup() throws Exception {
+
+    }
+
+    /**
+     * Perform common clean up for each test case.
      *
      * @throws Exception
      */
     @After
     public void teardown() throws Exception {
-        if (serverThread != null) {
-            serverThread.interrupt();
-        }
-        if (server != null) {
-            server.stopServer();
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/StartStopServerTest.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/StartStopServerTest.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/StartStopServerTest.java
deleted file mode 100644
index 37b1123..0000000
--- a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/tests/StartStopServerTest.java
+++ /dev/null
@@ -1,104 +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.funtest.server.tests;
-
-import org.apache.commons.codec.binary.Base64;
-import org.junit.Test;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertEquals;
-
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.methods.GetMethod;
-
-import java.io.StringReader;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonArray;
-
-import java.io.IOException;
-
-import org.apache.http.HttpStatus;
-
-/**
- * Simple test that starts the local ambari server,
- * tests it's status and shuts down the server.
- */
-public class StartStopServerTest extends ServerTestBase {
-  /**
-   * Waits for the ambari server to startup and then checks it's
-   * status by querying /api/v1/stacks (does not touch the DB)
-   */
-  @Test
-  public void testServerStatus() throws IOException {
-    /**
-     * Query the ambari server for the list of stacks.
-     * A successful GET returns the list of stacks.
-     * We should get a json like:
-     * {
-     *   "href" : "http://localhost:9995/api/v1/stacks",
-     *   "items" : [
-     *   {
-     *     "href" : "http://localhost:9995/api/v1/stacks/HDP",
-     *     "Stacks" : {
-     *     "stack_name" : "HDP"
-     *     }
-     *   }
-     *  ]
-     * }
-     */
-
-    /**
-     * Test URL for GETting the status of the ambari server
-     */
-    String stacksPath = "/api/v1/stacks";
-    String stacksUrl = String.format(SERVER_URL_FORMAT, serverPort) + stacksPath;
-    HttpClient httpClient = new HttpClient();
-    GetMethod getMethod = new GetMethod(stacksUrl);
-
-    try {
-      getMethod.addRequestHeader("Authorization", getBasicAuthentication());
-      getMethod.addRequestHeader("X-Requested-By", "ambari");
-      int statusCode = httpClient.executeMethod(getMethod);
-
-      assertEquals(HttpStatus.SC_OK, statusCode); // HTTP status code 200
-
-      String responseBody = getMethod.getResponseBodyAsString();
-
-      assertTrue(responseBody != null); // Make sure response body is valid
-
-      JsonElement jsonElement = new JsonParser().parse(new JsonReader(new StringReader(responseBody)));
-
-      assertTrue (jsonElement != null); // Response was a JSON string
-
-      JsonObject jsonObject = jsonElement.getAsJsonObject();
-
-      assertTrue (jsonObject.has("items"));  // Should have "items" entry
-
-      JsonArray stacksArray = jsonObject.get("items").getAsJsonArray();
-
-      assertTrue (stacksArray.size() > 0); // Should have at least one stack
-
-    } finally {
-      getMethod.releaseConnection();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/utils/ClusterUtils.java
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/utils/ClusterUtils.java b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/utils/ClusterUtils.java
index 9799892..8cf09c2 100644
--- a/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/utils/ClusterUtils.java
+++ b/ambari-funtest/src/test/java/org/apache/ambari/funtest/server/utils/ClusterUtils.java
@@ -23,6 +23,7 @@ import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
+import org.apache.ambari.funtest.server.AmbariUserRole;
 import org.apache.ambari.funtest.server.ClusterConfigParams;
 import org.apache.ambari.funtest.server.ConnectionParams;
 import org.apache.ambari.funtest.server.WebRequest;
@@ -31,6 +32,7 @@ import org.apache.ambari.funtest.server.api.cluster.AddDesiredConfigurationWebRe
 import org.apache.ambari.funtest.server.api.cluster.CreateClusterWebRequest;
 import org.apache.ambari.funtest.server.api.cluster.CreateConfigurationWebRequest;
 import org.apache.ambari.funtest.server.api.cluster.GetRequestStatusWebRequest;
+import org.apache.ambari.funtest.server.api.cluster.SetUserPrivilegeWebRequest;
 import org.apache.ambari.funtest.server.api.host.AddHostWebRequest;
 import org.apache.ambari.funtest.server.api.host.RegisterHostWebRequest;
 import org.apache.ambari.funtest.server.api.service.AddServiceWebRequest;
@@ -38,10 +40,15 @@ import org.apache.ambari.funtest.server.api.service.InstallServiceWebRequest;
 import org.apache.ambari.funtest.server.api.servicecomponent.AddServiceComponentWebRequest;
 import org.apache.ambari.funtest.server.api.servicecomponenthost.BulkAddServiceComponentHostsWebRequest;
 import org.apache.ambari.funtest.server.api.servicecomponenthost.BulkSetServiceComponentHostStateWebRequest;
+import org.apache.ambari.funtest.server.api.user.CreateUserWebRequest;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.controller.AmbariServer;
+import org.apache.ambari.server.orm.entities.PrincipalTypeEntity;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.State;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -49,6 +56,8 @@ import java.util.Map;
 
 public class ClusterUtils {
 
+    private static Log LOG = LogFactory.getLog(ClusterUtils.class);
+
     @Inject
     private Injector injector;
 
@@ -60,6 +69,11 @@ public class ClusterUtils {
         String clusterVersion = "HDP-2.2.0";
 
         /**
+         * Create a cluster
+         */
+        jsonResponse = RestApiUtils.executeRequest(new CreateClusterWebRequest(serverParams, clusterName, clusterVersion));
+
+        /**
          * Register a host
          */
         if (injector == null) {
@@ -81,11 +95,6 @@ public class ClusterUtils {
         }
 
         /**
-         * Create a cluster
-         */
-        jsonResponse = RestApiUtils.executeRequest(new CreateClusterWebRequest(serverParams, clusterName, clusterVersion));
-
-        /**
          * Add the registered host to the new cluster
          */
         jsonResponse =  RestApiUtils.executeRequest(new AddHostWebRequest(serverParams, clusterName, hostName));
@@ -145,8 +154,10 @@ public class ClusterUtils {
          */
         jsonResponse = RestApiUtils.executeRequest(new BulkSetServiceComponentHostStateWebRequest(serverParams,
                     clusterName, State.INIT, State.INSTALLED));
-        int requestId = parseRequestId(jsonResponse);
-        RequestStatusPoller.poll(serverParams, clusterName, requestId);
+        if (!jsonResponse.isJsonNull()) {
+            int requestId = parseRequestId(jsonResponse);
+            RequestStatusPoller.poll(serverParams, clusterName, requestId);
+        }
 
         /**
          * Start the service component hosts
@@ -154,8 +165,10 @@ public class ClusterUtils {
 
         jsonResponse = RestApiUtils.executeRequest(new BulkSetServiceComponentHostStateWebRequest(serverParams,
                 clusterName, State.INSTALLED, State.STARTED));
-        requestId = parseRequestId(jsonResponse);
-        RequestStatusPoller.poll(serverParams, clusterName, requestId);
+        if (!jsonResponse.isJsonNull()) {
+            int requestId = parseRequestId(jsonResponse);
+            RequestStatusPoller.poll(serverParams, clusterName, requestId);
+        }
 
         /**
          * Start the service
@@ -164,6 +177,103 @@ public class ClusterUtils {
     }
 
     /**
+     * Creates a user with the specified role.
+     *
+     * @param connectionParams
+     * @param clusterName
+     * @param userName
+     * @param password
+     * @param userRole
+     * @throws Exception
+     */
+    public static void createUser(ConnectionParams connectionParams, String clusterName,String userName,
+                                 String password, AmbariUserRole userRole ) throws Exception {
+        JsonElement jsonResponse;
+
+        jsonResponse = RestApiUtils.executeRequest(new CreateUserWebRequest(connectionParams, userName, password,
+                CreateUserWebRequest.ActiveUser.TRUE, CreateUserWebRequest.AdminUser.FALSE));
+
+        LOG.info(jsonResponse);
+
+        if (userRole != AmbariUserRole.NONE) {
+            jsonResponse = RestApiUtils.executeRequest(new SetUserPrivilegeWebRequest(connectionParams,
+                    clusterName, userName, userRole, PrincipalTypeEntity.USER_PRINCIPAL_TYPE_NAME));
+
+            LOG.info(jsonResponse);
+        }
+    }
+
+    /**
+     * Creates a user with CLUSTER.USER privilege.
+     *
+     * @param connectionParams
+     * @param clusterName
+     * @param userName
+     * @param password
+     * @throws Exception
+     */
+    public static void createUserClusterUser(ConnectionParams connectionParams, String clusterName,
+                                              String userName, String password) throws Exception {
+        createUser(connectionParams, clusterName, userName, password, AmbariUserRole.CLUSTER_USER);
+    }
+
+    /**
+     * Creates a user with SERVICE.OPERATOR privilege
+     *
+     * @param connectionParams
+     * @param clusterName
+     * @param userName
+     * @param password
+     * @throws Exception
+     */
+    public static void createUserServiceOperator(ConnectionParams connectionParams, String clusterName,
+                                              String userName, String password) throws Exception {
+        createUser(connectionParams, clusterName, userName, password, AmbariUserRole.SERVICE_OPERATOR);
+    }
+
+    /**
+     * Creates a user with SERVICE.ADMINISTRATOR privilege
+     *
+     * @param connectionParams
+     * @param clusterName
+     * @param userName
+     * @param password
+     * @throws Exception
+     */
+    public static void createUserServiceAdministrator(ConnectionParams connectionParams, String clusterName,
+                                              String userName, String password) throws Exception {
+        createUser(connectionParams, clusterName, userName, password, AmbariUserRole.SERVICE_ADMINISTRATOR);
+    }
+
+    /**
+     * Creates a user with CLUSTER.OPERATOR privilege
+     *
+     * @param connectionParams
+     * @param clusterName
+     * @param userName
+     * @param password
+     * @throws Exception
+     */
+    public static void createUserClusterOperator(ConnectionParams connectionParams, String clusterName,
+                                              String userName, String password) throws Exception {
+        createUser(connectionParams, clusterName, userName, password, AmbariUserRole.CLUSTER_OPERATOR);
+    }
+
+    /**
+     * Creates a user with CLUSTER.ADMINISTRATOR privilege.
+     *
+     * @param connectionParams
+     * @param clusterName
+     * @param userName
+     * @param password
+     * @throws Exception
+     */
+    public static void createUserClusterAdministrator(ConnectionParams connectionParams, String clusterName,
+                                              String userName, String password) throws Exception {
+        createUser(connectionParams, clusterName, userName, password, AmbariUserRole.CLUSTER_ADMINISTRATOR);
+    }
+
+    /**
      * Parses a JSON response string for  { "Requests" : { "id" : "2" } }
      *
      * @param jsonResponse

http://git-wip-us.apache.org/repos/asf/ambari/blob/f2e797ab/ambari-funtest/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/ambari-funtest/src/test/resources/log4j.properties b/ambari-funtest/src/test/resources/log4j.properties
index f6767d3..2590ab0 100644
--- a/ambari-funtest/src/test/resources/log4j.properties
+++ b/ambari-funtest/src/test/resources/log4j.properties
@@ -12,10 +12,10 @@
 
 # log4j configuration used during build and unit tests
 
-log4j.rootLogger=DEBUG,stdout
+log4j.rootLogger=INFO,stdout
 log4j.threshhold=ALL
 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c{2} (%F:%M(%L)) - %m%n
 
-log4j.logger.org.apache.ambari=DEBUG
+log4j.logger.org.apache.ambari=INFO