/*
 * 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.solr.security;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.invoke.MethodHandles;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import com.codahale.metrics.MetricRegistry;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.BaseHttpSolrClient;
import org.apache.solr.client.solrj.impl.HttpClientUtil;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.GenericSolrRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.RequestWriter.StringPayloadContentWriter;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.request.V2Request;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.cloud.SolrCloudAuthTestCase;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.TimeSource;
import org.apache.solr.common.util.Utils;
import org.apache.solr.util.LogLevel;
import org.apache.solr.util.SolrCLI;
import org.apache.solr.util.TimeOut;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.singletonMap;

public class BasicAuthIntegrationTest extends SolrCloudAuthTestCase {

  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

  private static final String COLLECTION = "authCollection";

  @Before
  public void setupCluster() throws Exception {
    configureCluster(3)
        .addConfig("conf", configset("cloud-minimal"))
        .configure();

    CollectionAdminRequest.createCollection(COLLECTION, "conf", 3, 1).process(cluster.getSolrClient());
    
    cluster.waitForActiveCollection(COLLECTION, 3, 3);
  }
  
  @After
  public void tearDownCluster() throws Exception {
    shutdownCluster();
  }

  @Test
  //commented 9-Aug-2018 @BadApple(bugUrl="https://issues.apache.org/jira/browse/SOLR-12028") // 21-May-2018
  // commented out on: 17-Feb-2019   @BadApple(bugUrl="https://issues.apache.org/jira/browse/SOLR-12028") // annotated on: 24-Dec-2018
  @LogLevel("org.apache.solr.security=DEBUG")
  public void testBasicAuth() throws Exception {
    boolean isUseV2Api = random().nextBoolean();
    String authcPrefix = "/admin/authentication";
    String authzPrefix = "/admin/authorization";
    if(isUseV2Api){
      authcPrefix = "/____v2/cluster/security/authentication";
      authzPrefix = "/____v2/cluster/security/authorization";
    }

    NamedList<Object> rsp;
    HttpClient cl = null;
    try {
      cl = HttpClientUtil.createClient(null);

      JettySolrRunner randomJetty = cluster.getRandomJetty(random());
      String baseUrl = randomJetty.getBaseUrl().toString();
      verifySecurityStatus(cl, baseUrl + authcPrefix, "/errorMessages", null, 20);
      zkClient().setData("/security.json", STD_CONF.replaceAll("'", "\"").getBytes(UTF_8), true);
      verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/class", "solr.BasicAuthPlugin", 20);

      randomJetty.stop();
      
      cluster.waitForJettyToStop(randomJetty);
      
      randomJetty.start();
      
      cluster.waitForAllNodes(30);
      
      cluster.waitForActiveCollection(COLLECTION, 3, 3);
      
      baseUrl = randomJetty.getBaseUrl().toString();
      verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/class", "solr.BasicAuthPlugin", 20);
      assertNumberOfMetrics(16); // Basic auth metrics available
      assertAuthMetricsMinimums(1, 0, 1, 0, 0, 0);
      assertPkiAuthMetricsMinimums(0, 0, 0, 0, 0, 0);
      
      String command = "{\n" +
          "'set-user': {'harry':'HarryIsCool'}\n" +
          "}";

      @SuppressWarnings({"rawtypes"})
      final SolrRequest genericReq;
      if (isUseV2Api) {
        genericReq = new V2Request.Builder("/cluster/security/authentication").POST().build();
      } else {
        genericReq = new GenericSolrRequest(SolrRequest.METHOD.POST, authcPrefix, new ModifiableSolrParams());
        ((GenericSolrRequest)genericReq).setContentWriter(new StringPayloadContentWriter(command, CommonParams.JSON_MIME));
      }

      // avoid bad connection races due to shutdown
      cluster.getSolrClient().getHttpClient().getConnectionManager().closeExpiredConnections();
      cluster.getSolrClient().getHttpClient().getConnectionManager().closeIdleConnections(1, TimeUnit.MILLISECONDS);
      
      BaseHttpSolrClient.RemoteSolrException exp = expectThrows(BaseHttpSolrClient.RemoteSolrException.class, () -> {
        cluster.getSolrClient().request(genericReq);
      });
      assertEquals(401, exp.code());
      assertAuthMetricsMinimums(2, 0, 2, 0, 0, 0);
      assertPkiAuthMetricsMinimums(0, 0, 0, 0, 0, 0);
      
      command = "{\n" +
          "'set-user': {'harry':'HarryIsUberCool'}\n" +
          "}";

      HttpPost httpPost = new HttpPost(baseUrl + authcPrefix);
      setAuthorizationHeader(httpPost, makeBasicAuthHeader("solr", "SolrRocks"));
      httpPost.setEntity(new ByteArrayEntity(command.getBytes(UTF_8)));
      httpPost.addHeader("Content-Type", "application/json; charset=UTF-8");
      verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication.enabled", "true", 20);
      HttpResponse r = cl.execute(httpPost);
      int statusCode = r.getStatusLine().getStatusCode();
      Utils.consumeFully(r.getEntity());
      assertEquals("proper_cred sent, but access denied", 200, statusCode);
      assertPkiAuthMetricsMinimums(0, 0, 0, 0, 0, 0);
      assertAuthMetricsMinimums(4, 1, 3, 0, 0, 0);

      baseUrl = cluster.getRandomJetty(random()).getBaseUrl().toString();

      verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/credentials/harry", NOT_NULL_PREDICATE, 20);
      command = "{\n" +
          "'set-user-role': {'harry':'admin'}\n" +
          "}";

      executeCommand(baseUrl + authzPrefix, cl,command, "solr", "SolrRocks");
      assertAuthMetricsMinimums(5, 2, 3, 0, 0, 0);

      baseUrl = cluster.getRandomJetty(random()).getBaseUrl().toString();
      verifySecurityStatus(cl, baseUrl + authzPrefix, "authorization/user-role/harry", NOT_NULL_PREDICATE, 20);

      executeCommand(baseUrl + authzPrefix, cl, Utils.toJSONString(singletonMap("set-permission", Utils.makeMap
          ("collection", "x",
              "path", "/update/*",
              "role", "dev"))), "harry", "HarryIsUberCool" );

      verifySecurityStatus(cl, baseUrl + authzPrefix, "authorization/permissions[1]/collection", "x", 20);
      assertAuthMetricsMinimums(8, 3, 5, 0, 0, 0);

      executeCommand(baseUrl + authzPrefix, cl,Utils.toJSONString(singletonMap("set-permission", Utils.makeMap
          ("name", "collection-admin-edit", "role", "admin"))), "harry", "HarryIsUberCool"  );
      verifySecurityStatus(cl, baseUrl + authzPrefix, "authorization/permissions[2]/name", "collection-admin-edit", 20);
      assertAuthMetricsMinimums(10, 4, 6, 0, 0, 0);

      CollectionAdminRequest.Reload reload = CollectionAdminRequest.reloadCollection(COLLECTION);

      try (HttpSolrClient solrClient = getHttpSolrClient(baseUrl)) {
        expectThrows(BaseHttpSolrClient.RemoteSolrException.class, () -> solrClient.request(reload));
        reload.setMethod(SolrRequest.METHOD.POST);
        expectThrows(BaseHttpSolrClient.RemoteSolrException.class, () -> solrClient.request(reload));
      }
      cluster.getSolrClient().request(CollectionAdminRequest.reloadCollection(COLLECTION)
          .setBasicAuthCredentials("harry", "HarryIsUberCool"));

      expectThrows(BaseHttpSolrClient.RemoteSolrException.class, () -> {
        cluster.getSolrClient().request(CollectionAdminRequest.reloadCollection(COLLECTION)
            .setBasicAuthCredentials("harry", "Cool12345"));
      });
      assertAuthMetricsMinimums(14, 5, 8, 1, 0, 0);

      executeCommand(baseUrl + authzPrefix, cl,"{set-permission : { name : update , role : admin}}", "harry", "HarryIsUberCool");

      UpdateRequest del = new UpdateRequest().deleteByQuery("*:*");
      del.setBasicAuthCredentials("harry","HarryIsUberCool");
      del.setCommitWithin(10);
      del.process(cluster.getSolrClient(), COLLECTION);

      //Test for SOLR-12514. Create a new jetty . This jetty does not have the collection.
      //Make a request to that jetty and it should fail
      JettySolrRunner aNewJetty = cluster.startJettySolrRunner();
      SolrClient aNewClient = aNewJetty.newClient();
      UpdateRequest delQuery = null;
      delQuery = new UpdateRequest().deleteByQuery("*:*");
      delQuery.setBasicAuthCredentials("harry","HarryIsUberCool");
      delQuery.process(aNewClient, COLLECTION);//this should succeed
      try {
        BaseHttpSolrClient.RemoteSolrException e = expectThrows(BaseHttpSolrClient.RemoteSolrException.class, () -> {
          new UpdateRequest().deleteByQuery("*:*").process(aNewClient, COLLECTION);
        });
        assertTrue(e.getMessage(), e.getMessage().contains("Authentication failed"));
      } finally {
        aNewClient.close();
        cluster.stopJettySolrRunner(aNewJetty);
      }

      addDocument("harry","HarryIsUberCool","id", "4");

      executeCommand(baseUrl + authcPrefix, cl, "{set-property : { blockUnknown: true}}", "harry", "HarryIsUberCool");
      verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/blockUnknown", "true", 20, "harry", "HarryIsUberCool");
      verifySecurityStatus(cl, baseUrl + "/admin/info/key", "key", NOT_NULL_PREDICATE, 20);
      assertAuthMetricsMinimums(17, 8, 8, 1, 0, 0);

      String[] toolArgs = new String[]{
          "status", "-solr", baseUrl};
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      PrintStream stdoutSim = new PrintStream(baos, true, StandardCharsets.UTF_8.name());
      SolrCLI.StatusTool tool = new SolrCLI.StatusTool(stdoutSim);
      try {
        System.setProperty("basicauth", "harry:HarryIsUberCool");
        tool.runTool(SolrCLI.processCommandLineArgs(SolrCLI.joinCommonAndToolOptions(tool.getOptions()), toolArgs));
        @SuppressWarnings({"rawtypes"})
        Map obj = (Map) Utils.fromJSON(new ByteArrayInputStream(baos.toByteArray()));
        assertTrue(obj.containsKey("version"));
        assertTrue(obj.containsKey("startTime"));
        assertTrue(obj.containsKey("uptime"));
        assertTrue(obj.containsKey("memory"));
      } catch (Exception e) {
        log.error("RunExampleTool failed due to: {}; stdout from tool prior to failure: {}"
            , e, baos.toString(StandardCharsets.UTF_8.name())); // nowarn
      }

      SolrParams params = new MapSolrParams(Collections.singletonMap("q", "*:*"));
      // Query that fails due to missing credentials
      exp = expectThrows(BaseHttpSolrClient.RemoteSolrException.class, () -> {
        cluster.getSolrClient().query(COLLECTION, params);
      });
      assertEquals(401, exp.code());
      assertAuthMetricsMinimums(19, 8, 8, 1, 2, 0);
      assertPkiAuthMetricsMinimums(3, 3, 0, 0, 0, 0);

      // Query that succeeds
      GenericSolrRequest req = new GenericSolrRequest(SolrRequest.METHOD.GET, "/select", params);
      req.setBasicAuthCredentials("harry", "HarryIsUberCool");
      cluster.getSolrClient().request(req, COLLECTION);
      
      assertAuthMetricsMinimums(20, 8, 8, 1, 2, 0);
      assertPkiAuthMetricsMinimums(10, 10, 0, 0, 0, 0);

      addDocument("harry","HarryIsUberCool","id", "5");
      assertAuthMetricsMinimums(23, 11, 9, 1, 2, 0);
      assertPkiAuthMetricsMinimums(14, 14, 0, 0, 0, 0);

      // Reindex collection depends on streaming request that needs to authenticate against new collection
      CollectionAdminRequest.ReindexCollection reindexReq = CollectionAdminRequest.reindexCollection(COLLECTION);
      reindexReq.setBasicAuthCredentials("harry", "HarryIsUberCool");
      cluster.getSolrClient().request(reindexReq, COLLECTION);
      assertAuthMetricsMinimums(24, 12, 9, 1, 2, 0);
      assertPkiAuthMetricsMinimums(15, 15, 0, 0, 0, 0);

      // Validate forwardCredentials
      assertEquals(1, executeQuery(params("q", "id:5"), "harry", "HarryIsUberCool").getResults().getNumFound());
      assertAuthMetricsMinimums(25, 13, 9, 1, 2, 0);
      assertPkiAuthMetricsMinimums(19, 19, 0, 0, 0, 0);
      executeCommand(baseUrl + authcPrefix, cl, "{set-property : { forwardCredentials: true}}", "harry", "HarryIsUberCool");
      verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication/forwardCredentials", "true", 20, "harry", "HarryIsUberCool");
      assertEquals(1, executeQuery(params("q", "id:5"), "harry", "HarryIsUberCool").getResults().getNumFound());
      assertAuthMetricsMinimums(32, 20, 9, 1, 2, 0);
      assertPkiAuthMetricsMinimums(19, 19, 0, 0, 0, 0);
      
      executeCommand(baseUrl + authcPrefix, cl, "{set-property : { blockUnknown: false}}", "harry", "HarryIsUberCool");
    } finally {
      if (cl != null) {
        HttpClientUtil.close(cl);
      }
    }
  }

  private void assertNumberOfMetrics(int num) {
    MetricRegistry registry0 = cluster.getJettySolrRunner(0).getCoreContainer().getMetricManager().registry("solr.node");
    assertNotNull(registry0);

    assertEquals(num, registry0.getMetrics().entrySet().stream().filter(e -> e.getKey().startsWith("SECURITY")).count());
  }

  private QueryResponse executeQuery(ModifiableSolrParams params, String user, String pass) throws IOException, SolrServerException {
    @SuppressWarnings({"rawtypes"})
    SolrRequest req = new QueryRequest(params);
    req.setBasicAuthCredentials(user, pass);
    QueryResponse resp = (QueryResponse) req.process(cluster.getSolrClient(), COLLECTION);
    assertNull(resp.getException());
    assertEquals(0, resp.getStatus());
    return resp;
  }

  private void addDocument(String user, String pass, String... fields) throws IOException, SolrServerException {
    SolrInputDocument doc = new SolrInputDocument();
    boolean isKey = true;
    String key = null;
    for (String field : fields) {
      if (isKey) {
        key = field;
        isKey = false;
      } else {
        doc.setField(key, field);
      }
    }
    UpdateRequest update = new UpdateRequest();
    update.setBasicAuthCredentials(user, pass);
    update.add(doc);
    cluster.getSolrClient().request(update, COLLECTION);
    update.commit(cluster.getSolrClient(), COLLECTION);
  }

  public static void executeCommand(String url, HttpClient cl, String payload,
                                    String user, String pwd) throws Exception {

    // HACK: work around for SOLR-13464...
    //
    // note the authz/authn objects in use on each node before executing the command,
    // then wait until we see new objects on every node *after* executing the command
    // before returning...
    final Set<Map.Entry<String,Object>> initialPlugins
      = getAuthPluginsInUseForCluster(url).entrySet();

    HttpPost httpPost;
    HttpResponse r;
    httpPost = new HttpPost(url);
    setAuthorizationHeader(httpPost, makeBasicAuthHeader(user, pwd));
    httpPost.setEntity(new ByteArrayEntity(payload.getBytes(UTF_8)));
    httpPost.addHeader("Content-Type", "application/json; charset=UTF-8");
    r = cl.execute(httpPost);
    String response = IOUtils.toString(r.getEntity().getContent(), StandardCharsets.UTF_8);
    assertEquals("Non-200 response code. Response was " + response, 200, r.getStatusLine().getStatusCode());
    assertFalse("Response contained errors: " + response, response.contains("errorMessages"));
    Utils.consumeFully(r.getEntity());

    // HACK (continued)...
    final TimeOut timeout = new TimeOut(30, TimeUnit.SECONDS, TimeSource.NANO_TIME);
    timeout.waitFor("core containers never fully updated their auth plugins",
                    () -> {
                      final Set<Map.Entry<String,Object>> tmpSet
                        = getAuthPluginsInUseForCluster(url).entrySet();
                      tmpSet.retainAll(initialPlugins);
                      return tmpSet.isEmpty();
                    });
  }

  public static Replica getRandomReplica(DocCollection coll, Random random) {
    ArrayList<Replica> l = new ArrayList<>();

    for (Slice slice : coll.getSlices()) {
      l.addAll(slice.getReplicas());
    }
    Collections.shuffle(l, random);
    return l.isEmpty() ? null : l.get(0);
  }

  //the password is 'SolrRocks'
  //this could be generated everytime. But , then we will not know if there is any regression
  protected static final String STD_CONF = "{\n" +
      "  'authentication':{\n" +
      "    'blockUnknown':'false',\n" +
      "    'class':'solr.BasicAuthPlugin',\n" +
      "    'credentials':{'solr':'orwp2Ghgj39lmnrZOTm7Qtre1VqHFDfwAEzr0ApbN3Y= Ju5osoAqOX8iafhWpPP01E5P+sg8tK8tHON7rCYZRRw='}},\n" +
      "  'authorization':{\n" +
      "    'class':'solr.RuleBasedAuthorizationPlugin',\n" +
      "    'user-role':{'solr':'admin'},\n" +
      "    'permissions':[{'name':'security-edit','role':'admin'}]}}";
}
