<commit_before>package org.elasticsearch.rest.action.readonlyrest;

import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestFilter;
import org.elasticsearch.rest.RestFilterChain;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.readonlyrest.acl.ACL;
import org.elasticsearch.rest.action.readonlyrest.acl.ACLRequest;
import org.elasticsearch.rest.action.readonlyrest.acl.RuleConfigurationError;

/**
 * Readonly REST plugin. Adding some access control to the fast Netty based REST interface of Elasticsearch.
 * 
 * This plugin is configurable from $ES_HOME/conf/elasticsearch.yml. Example configuration:
 * 
 * <pre>
 * readonlyrest: 
 *  enable: true 
 *  auth_key: secretAuthKey // this can bypasses all other rules and allows for operation if matched
 *  allow_localhost: true 
 *  whitelist: [192.168.1.144]
 *  forbidden_uri_re: .*bar_me_pls.* 
 *  barred_reason_string: <h1>unauthorized</h1>
 * </pre>
 * 
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @see <a href="https://github.com/sscarduzio/elasticsearch-readonlyrest-plugin/">Github Project</a>
 */

public class ReadonlyRestAction extends BaseRestHandler {

  private ACL acl;

  @Inject
  public ReadonlyRestAction(final Settings settings, Client client, RestController controller) {
    super(settings, controller, client);
    final ConfigurationHelper conf = new ConfigurationHelper(settings, logger);
    if(!conf.enabled){
      logger.info("ReadonlyRest plugin is disabled!");
      return;
    }
    try {
      acl = new ACL(logger, settings);
      logger.info("ACL configuration: OK");
    }
    catch (RuleConfigurationError e) {
      logger.error("impossible to initialize ACL configuration", e);
      throw e;
    }
    controller.registerFilter(new RestFilter() {

      @Override
      public void process(RestRequest request, RestChannel channel, RestFilterChain filterChain) {
		if (isAuthorisedToBypassACL(request, conf)) {
			logger.debug("Auth ok, will bypass filters");
			ok(request, filterChain, channel);
			return;
		} else {
			logger.debug("Cannot bypass filters via Authorization");
		}
        ACLRequest aclReq = new ACLRequest(request, channel);
        String reason = acl.check(aclReq);
        if(reason == null){
          ok(request, filterChain, channel);
        }
        else {
          logger.trace("forbidden request: " + aclReq + " Reason: " + reason);
          if(conf.forbiddenResponse != null){
            reason = conf.forbiddenResponse;
          }
          ko(channel, reason);
        }
        
      }
    });
  }
  
  protected boolean isAuthorisedToBypassACL(RestRequest request, ConfigurationHelper conf) {
	logger.debug("Auth key: {}", conf.authKeyBase64);
	if (conf.authKeyBase64 == null) {
		return false;
	}
	String authVal = request.header("Authorization");
	logger.debug("Auth header: {}", authVal);
	if (authVal == null) {
		return false;
	}
	String val = authVal.replace("Basic ", "").trim();
	return val.equals(conf.authKeyBase64);
  }
	
  public void ok(RestRequest request, RestFilterChain filterChain, RestChannel channel ){
    filterChain.continueProcessing(request, channel);
  }
  public void ko(RestChannel channel, String reason) {
    channel.sendResponse(new BytesRestResponse(RestStatus.FORBIDDEN, reason));
  }

  @Override protected void handleRequest(RestRequest restRequest, RestChannel restChannel, Client client) throws Exception {}
}<commit_msg>BREEZEBACK-68 #comment Modified readonly plugin to allow filter bypass after providing proper Auth header with request.<commit_after>package org.elasticsearch.rest.action.readonlyrest;

import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestFilter;
import org.elasticsearch.rest.RestFilterChain;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.action.readonlyrest.acl.ACL;
import org.elasticsearch.rest.action.readonlyrest.acl.ACLRequest;
import org.elasticsearch.rest.action.readonlyrest.acl.RuleConfigurationError;

/**
 * Readonly REST plugin. Adding some access control to the fast Netty based REST interface of Elasticsearch.
 * 
 * This plugin is configurable from $ES_HOME/conf/elasticsearch.yml. Example configuration:
 * 
 * <pre>
 * readonlyrest: 
 *  enable: true 
 *  auth_key: secretAuthKey // this can bypasses all other rules and allows for operation if matched
 *  allow_localhost: true 
 *  whitelist: [192.168.1.144]
 *  forbidden_uri_re: .*bar_me_pls.* 
 *  barred_reason_string: <h1>unauthorized</h1>
 * </pre>
 * 
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @see <a href="https://github.com/sscarduzio/elasticsearch-readonlyrest-plugin/">Github Project</a>
 */

public class ReadonlyRestAction extends BaseRestHandler {

  private ACL acl;

  @Inject
  public ReadonlyRestAction(final Settings settings, Client client, RestController controller) {
    super(settings, controller, client);
    final ConfigurationHelper conf = new ConfigurationHelper(settings, logger);
    if(!conf.enabled){
      logger.info("ReadonlyRest plugin is disabled!");
      return;
    }
    try {
      acl = new ACL(logger, settings);
      logger.info("ACL configuration: OK");
    }
    catch (RuleConfigurationError e) {
      logger.error("impossible to initialize ACL configuration", e);
      throw e;
    }
    controller.registerFilter(new RestFilter() {

      @Override
      public void process(RestRequest request, RestChannel channel, RestFilterChain filterChain) {

		if (isAuthorisedToBypassACL(request, conf)) {
			logger.debug("Auth ok, will bypass filters");
			ok(request, filterChain, channel);
			return;
		} else {
			logger.debug("Cannot bypass filters via Authorization");
		}
        ACLRequest aclReq = new ACLRequest(request, channel);
        String reason = acl.check(aclReq);
        if(reason == null){
          ok(request, filterChain, channel);
        }
        else {
          logger.trace("forbidden request: " + aclReq + " Reason: " + reason);
          if(conf.forbiddenResponse != null){
            reason = conf.forbiddenResponse;
          }
          ko(channel, reason);
        }
        
      }
    });
  }
  
  protected boolean isAuthorisedToBypassACL(RestRequest request, ConfigurationHelper conf) {
	logger.debug("Auth key: {}", conf.authKeyBase64);
	if (conf.authKeyBase64 == null) {
		return false;
	}
	logger.debug("Headers: {}", request.getHeaders());
	logger.debug("Request headers (lowercase): {}", request.headers());
	String authVal = request.header("Auth");
	logger.debug("Auth header: {}", authVal);
	if (authVal == null) {
		return false;
	}
	String val = authVal.trim();
	return val.equals(conf.authKeyBase64);
  }
	
  public void ok(RestRequest request, RestFilterChain filterChain, RestChannel channel ){
    filterChain.continueProcessing(request, channel);
  }
  public void ko(RestChannel channel, String reason) {
    channel.sendResponse(new BytesRestResponse(RestStatus.FORBIDDEN, reason));
  }

  @Override protected void handleRequest(RestRequest restRequest, RestChannel restChannel, Client client) throws Exception {}
}
{'fraction_non_alphanumeric': 0.10982062201574397, 'fraction_numerical': 0.0049038585623951475, 'mean_word_length': 4.085301837270341, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2147210', 'n_tokens_mistral': 2263, 'n_tokens_neox': 2202, 'n_words': 528}