Package org.elasticsearch.plugins.security.service.permission

Source Code of org.elasticsearch.plugins.security.service.permission.PermEvaluator$Perm

package org.elasticsearch.plugins.security.service.permission;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.plugins.security.MalformedConfigurationException;

public abstract class PermEvaluator<T> {

  protected static final ESLogger log = Loggers
      .getLogger(PermEvaluator.class);
  protected final String xSecurityConfiguration;
  protected XContentParser parser = null;

  protected PermEvaluator(final String xSecurityConfiguration) {
    super();

    if (xSecurityConfiguration == null || xSecurityConfiguration.isEmpty()) {
      throw new IllegalArgumentException(
          "securityconfiguration must not be null or empty");
    }

    this.xSecurityConfiguration = xSecurityConfiguration;

    // log.debug("Configuration: " + xSecurityConfiguration);
  }

  protected abstract T createFromString(String s);
 
  protected abstract T getDefaultPermLevelForEvaluator();

  protected abstract String getPermissionFieldName();

  public T evaluatePerm(final List<String> indices, final List<String> types,
      final InetAddress hostAddress, final UserRoleCallback callback)
          throws MalformedConfigurationException {
     
      /*if(indices==null || types == null || hostAddress == null) {
          throw new MalformedConfigurationException("Indices, types and hostAddress must not be null");
      }*/

    final List<Perm<T>> perms = new ArrayList<Perm<T>>();

    //final List<WildcardString> matchList = new ArrayList<WildcardString>();

    try {

      this.parser = XContentFactory.xContent(this.xSecurityConfiguration)
          .createParser(this.xSecurityConfiguration);

      final String permissionFieldName = this.getPermissionFieldName();

      XContentParser.Token token = null;
      String currentFieldName = null;
      Perm<T> currentPerm = null;
      while ((token = this.parser.nextToken()) != null) {

        if (token == XContentParser.Token.START_OBJECT) {
          currentPerm = new Perm<T>();

        } else if (token == XContentParser.Token.END_OBJECT) {

          if (currentPerm != null && perms.contains(currentPerm)) {
            log.error("Duplicate permissions " + currentPerm);
            throw new MalformedConfigurationException(
                "Duplicate permissions found");
          }

          /*if (currentPerm != null && !currentPerm.isValid()) {
                        log.error("Perm not valid " + currentPerm);
                        throw new MalformedConfigurationException(
                                "Invalid permission found");
                    }*/

          if (currentPerm != null) {
             
              if(currentPerm.permLevel == null){
                  currentPerm.permLevel = getDefaultPermLevelForEvaluator();
              }
             
            perms.add(currentPerm);
            currentPerm = null;
          }

        } else if (token == XContentParser.Token.FIELD_NAME) {
          currentFieldName = this.parser.currentName();

        } else if (token.isValue()) {

          if ("hosts".equals(currentFieldName)) {
            currentPerm.addInetAddress(this.parser.text());
          }
          if ("users".equals(currentFieldName)) {
            currentPerm.addUser(this.parser.text());
          }
          if ("roles".equals(currentFieldName)) {
            currentPerm.addRole(this.parser.text());
          } else if ("indices".equals(currentFieldName)) {
            currentPerm.addIndice(this.parser.text());
          } else if ("types".equals(currentFieldName)) {
            currentPerm.addType(this.parser.text());
          } else if (permissionFieldName.equals(currentFieldName)) {
            final String text = this.parser.text();
            currentPerm.setPermLevel(this
                .createFromString(text == null ? null : text
                    .trim()));
          }

        }

      }

    } catch (final Exception e) {
      throw new MalformedConfigurationException(e);
    } finally {
      this.parser.close();
    }
   
   
   
   
   

    log.debug("Checking " + perms.size() + " perms");

    T permLevel = null;

    for (final Perm<T> p : perms) {

      if (p.isDefault()) {
        permLevel = p.permLevel;
        if (log.isDebugEnabled()) {
          log.debug("Default set to " + permLevel);
        }
        break;
      }
    }

    if (permLevel == null) {
      throw new MalformedConfigurationException(
          "No default configuration found");
    }

    /*for (final Perm<T> p : perms) {

      for (final String ip : p.inetAddresses) {
        //matchList.add(new WildcardString(ip));
      }
    }*/

    final String clientHostName = hostAddress.getHostName();
    final String clientHostIp = hostAddress.getHostAddress();
   
    permloop: for (final Perm<T> p : perms) {

      if (p.isDefault()) {
        continue;
      }

      String _role = null;
      String _host = null;

      log.debug("Check perm " + p);

      // TODO difference between not here and []
      if (!p.users.isEmpty()
          && !p.users.contains("*")
          && (callback == null || callback.getRemoteuser() == null || !p.users
          .contains(callback.getRemoteuser()))) {
        if(callback != null) {
              log.debug("User " + callback.getRemoteuser()
          + " does not match, so skip this permission");
        } else {
            log.debug("No callback");
        }
        continue permloop;
      }

      log.debug("User "
          + (callback == null ? "" : callback.getRemoteuser())
          + " match");

      if (!p.roles.contains("*") && !p.roles.isEmpty()) {
        if (callback == null) {
          log.debug("Role does not match, so skip this permission");
          continue permloop;
        }

        for (final String role : p.roles) {
          if (callback.isRemoteUserInRole(role)) {
            log.debug("Role " + role + " match");
            _role = role;
            break;
          }
        }

        if (_role == null) {
          log.debug("Role does not match, so skip this permission");
          continue permloop;
        }
      }

      if (!p.inetAddresses.contains("*") && !p.inetAddresses.isEmpty()) {
        for (final String pinetAddress : p.inetAddresses) {
          if (isWildcardMatch(pinetAddress, clientHostName)
          || isWildcardMatch(pinetAddress, clientHostIp)) {

            log.debug("Host adress " + pinetAddress + " match");
            _host = pinetAddress;
            break;

          }

        }

        if (_host == null) {

          log.debug("Host adress ("
              + clientHostIp
              + "(ip) and "
              + clientHostName
              + " (hostname) does not match, so skip this permission");
          continue permloop;

        }

      }

      if (!p.types.isEmpty() && !p.types.contains("*")) {
       
        boolean typeMatch=false;
       
        typeloop:
        for (final String pType : p.types) {
         
          for (final String tType : types)
          {
            if (isWildcardMatch(tType, pType)) {
              log.debug("Type "+pType+" match " + tType + "");
              typeMatch=true;
              break typeloop;

            }else {
              log.debug("Type "+pType+" not match " + tType + "");
            }
           
          }
        }
       
        if(!typeMatch){
          log.debug("No type matches, so skip this permission ["
              + p.types + " != " + types + "]");
          continue permloop;
        }
      }

      log.debug("All types matches");

      if ( !p.indices.isEmpty() && !p.indices.contains("*")) {

       
        boolean indexMatch=false;
       
        indexloop:
                for (final String pIndex : p.indices) {
         
                    if(indices != null) {
                        for (final String tIndex : indices)
                        {
                            if (isWildcardMatch(tIndex, pIndex)) {
                                log.debug("Index "+pIndex+" match " + tIndex + "");
                                indexMatch=true;
                                break indexloop;

                            }else {
                                log.debug("Index "+pIndex+" not match " + tIndex + "");
                            }
                           
                        }
                    }
         
        }

        if(!indexMatch)
        {
         
          log.debug("No index matches, so skip this permission ["
              + p.indices + " != " + indices + "]");
          continue permloop;
        }
       
       
      }
     
     
      //START
      //added condition to check if indices provided are empty to validate the matching of index. This is required to allow requesting metadata queries like /_mapping, /_setting etc.
      //(contributed by Ram Kotamaraja)
      else
      if((indices == null || indices.isEmpty()) && !p.indices.isEmpty() && !p.indices.contains("*") ){

        log.debug("Not all indexes match because no index specified, so skip this permission ["
            + p.indices + " != " + indices + "]");
        continue permloop;
       
      }
      //END

      log.debug("All rules match, will apply " + p);
      return p.permLevel;

    }// end permloop

    log.debug("No rules matched, will apply default perm " + permLevel);
    return permLevel;

  }

  protected static class Perm<T> {

    private final List<String> inetAddresses = new ArrayList<String>();
    private final List<String> users = new ArrayList<String>();
    private final List<String> roles = new ArrayList<String>();
    private final List<String> indices = new ArrayList<String>();
    private final List<String> types = new ArrayList<String>();

    private T permLevel = null;

    public boolean isValid() {
      return this.permLevel != null;
    }

    // default is either all props empty and/or "*"
    public boolean isDefault() {

      if (this.inetAddresses.isEmpty() && this.users.isEmpty()
          && this.roles.isEmpty() && this.indices.isEmpty()
          && this.types.isEmpty()) {
        return true;
      }

      return (this.inetAddresses.isEmpty() ? true : this.inetAddresses
          .size() == 1 && "*".equals(this.inetAddresses.get(0)))
          && (this.users.isEmpty() ? true : this.users.size() == 1
          && "*".equals(this.users.get(0)))
          && (this.roles.isEmpty() ? true : this.roles.size() == 1
          && "*".equals(this.roles.get(0)))
          && (this.types.isEmpty() ? true : this.types.size() == 1
          && "*".equals(this.types.get(0)))
          && (this.indices.isEmpty() ? true
              : this.indices.size() == 1
              && "*".equals(this.indices.get(0)));
    }

    public void addInetAddress(final String inetAddress) {
      if (inetAddress == null || inetAddress.isEmpty()
          || inetAddress.contains(",")) {
        throw new IllegalArgumentException("'" + inetAddress
            + "' is not a valid inet address");
      }
      this.inetAddresses.add(inetAddress.trim());
    }

    public void addIndice(final String indice) {
      if (indice == null || indice.isEmpty() || indice.contains(",")) {
        throw new IllegalArgumentException("'" + indice
            + "' is not a valid index name");
      }
      this.indices.add(indice.trim());
    }

    public void addUser(final String user) {
      if (user == null || user.isEmpty() || user.contains(",")) {
        throw new IllegalArgumentException("'" + user
            + "' is not a valid user");
      }
      this.users.add(user.trim());
    }

    public void addRole(final String role) {
      if (role == null || role.isEmpty() || role.contains(",")) {
        throw new IllegalArgumentException("'" + role
            + "' is not a valid role");
      }
      this.roles.add(role.trim());
    }

    public void addType(final String type) {
      if (type == null || type.isEmpty() || type.contains(",")) {
        throw new IllegalArgumentException("'" + type
            + "' is not a valid type");
      }
      this.types.add(type.trim());
    }

    public void setPermLevel(final T permLevel) {

      if (permLevel == null) {
        throw new IllegalArgumentException("'" + permLevel
            + "' is not a valid permLevel");
      }

      this.permLevel = permLevel;
    }

    public Perm() {

    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result
          + (this.indices == null ? 0 : this.indices.hashCode());
      result = prime
          * result
          + (this.inetAddresses == null ? 0 : this.inetAddresses
              .hashCode());
      result = prime * result
          + (this.roles == null ? 0 : this.roles.hashCode());
      result = prime * result
          + (this.types == null ? 0 : this.types.hashCode());
      result = prime * result
          + (this.users == null ? 0 : this.users.hashCode());
      return result;
    }

    @Override
    public boolean equals(final Object obj) {
      if (this == obj) {
        // log.debug("perm ==");
        return true;
      }
      if (obj == null) {
        // log.debug("perm other null");
        return false;
      }
      if (this.getClass() != obj.getClass()) {
        // log.debug("perm class mismatch");
        return false;
      }
      final Perm<?> other = (Perm<?>) obj;
      if (this.indices == null) {
        if (other.indices != null) {
          return false;
        }
      } else if (!equalLists(this.indices, other.indices)) {
        // log.debug("perm list not match: indices");
        return false;
      }
      if (this.inetAddresses == null) {
        if (other.inetAddresses != null) {
          return false;
        }
      } else if (!equalLists(this.inetAddresses, other.inetAddresses)) {
        // log.debug("perm list not match: inetaddr");
        return false;
      }
      if (this.roles == null) {
        if (other.roles != null) {
          return false;
        }
      } else if (!equalLists(this.roles, other.roles)) {
        // log.debug("perm list not match: roles");
        return false;
      }
      if (this.users == null) {
        if (other.users != null) {
          return false;
        }
      } else if (!equalLists(this.users, other.users)) {
        // log.debug("perm list not match: users");
        return false;
      }

      if (this.types == null) {
        if (other.types != null) {
          return false;
        }
      } else if (!equalLists(this.types, other.types)) {
        // log.debug("perm list not match: types");
        return false;
      }

      return true;
    }

    @Override
    public String toString() {
      return "Perm [inetAddresses=" + this.inetAddresses + ", users="
          + this.users + ", roles=" + this.roles + ", indices="
          + this.indices + ", types=" + this.types + ", permLevel="
          + this.permLevel + ", isValid()=" + this.isValid()
          + ", isDefault()=" + this.isDefault() + "]";
    }

  }

  private static boolean equalLists(final List<String> one,
      final List<String> two) {
    if (one == null && two == null) {
      return true;
    }

    if (one == null && two != null || one != null && two == null
        || one.size() != two.size()) {
      return false;
    }

    return one.containsAll(two) && two.containsAll(one);
  }

 
  private boolean isWildcardMatch(String a, String b) {
   
    String escapedA = a.replace(".", "\\.").replace("*",
        ".*");
   
    Pattern p = Pattern.compile(escapedA);
    Matcher m = p.matcher(b);
    if(m.matches()){
      return true;
    } else {
      String escapedB = b.replace(".", "\\.").replace("*",
          ".*");
     
      p = Pattern.compile(escapedB);
      m = p.matcher(a);
      return m.matches();
    }
  }
 
}
TOP

Related Classes of org.elasticsearch.plugins.security.service.permission.PermEvaluator$Perm

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.