content: /*
   * 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 static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
  
  import java.util.HashMap;
  
  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.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.http.HttpStatus;
  import org.junit.Test;
  
  import com.google.gson.JsonElement;
  
  /**
   * 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;
      }
  }
  