org.apache.ranger.biz.KmsKeyMgr.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ranger.biz.KmsKeyMgr.java

Source

/*
 * 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.ranger.biz;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.security.auth.Subject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MediaType;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.PredicateUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.ProviderUtils;
import org.apache.hadoop.security.SecureClientLogin;
import org.apache.hadoop.security.authentication.util.KerberosName;
import org.apache.log4j.Logger;
import org.apache.ranger.common.ContextUtil;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.plugin.util.PasswordUtils;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RESTErrorUtil;
import org.apache.ranger.common.RangerConfigUtil;
import org.apache.ranger.common.SortField;
import org.apache.ranger.common.StringUtil;
import org.apache.ranger.db.RangerDaoManagerBase;
import org.apache.ranger.entity.XXService;
import org.apache.ranger.entity.XXServiceConfigMap;
import org.apache.ranger.plugin.model.RangerService;
import org.apache.ranger.plugin.util.KeySearchFilter;
import org.apache.ranger.view.VXKmsKey;
import org.apache.ranger.view.VXKmsKeyList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;

@Component
public class KmsKeyMgr {

    static final Logger logger = Logger.getLogger(KmsKeyMgr.class);

    private static final String KMS_KEY_LIST_URI = "v1/keys/names"; //GET
    private static final String KMS_ADD_KEY_URI = "v1/keys"; //POST
    private static final String KMS_ROLL_KEY_URI = "v1/key/${alias}"; //POST
    private static final String KMS_DELETE_KEY_URI = "v1/key/${alias}"; //DELETE
    private static final String KMS_KEY_METADATA_URI = "v1/key/${alias}/_metadata"; //GET
    private static final String KMS_URL_CONFIG = "provider";
    private static final String KMS_PASSWORD = "password";
    private static final String KMS_USERNAME = "username";
    private static Map<String, String> providerList = new HashMap<String, String>();
    private static int nextProvider = 0;
    static final String NAME_RULES = "hadoop.security.auth_to_local";
    static final String RANGER_AUTH_TYPE = "hadoop.security.authentication";
    private static final String KERBEROS_TYPE = "kerberos";
    private static final String ADMIN_USER_PRINCIPAL = "ranger.admin.kerberos.principal";
    private static final String ADMIN_USER_KEYTAB = "ranger.admin.kerberos.keytab";
    static final String HOST_NAME = "ranger.service.host";

    @Autowired
    ServiceDBStore svcStore;

    @Autowired
    RESTErrorUtil restErrorUtil;

    @Autowired
    RangerConfigUtil configUtil;

    @Autowired
    RangerDaoManagerBase rangerDaoManagerBase;

    @SuppressWarnings("unchecked")
    public VXKmsKeyList searchKeys(HttpServletRequest request, String repoName) throws Exception {
        String providers[] = null;
        try {
            providers = getKMSURL(repoName);
        } catch (Exception e) {
            logger.error("getKey(" + repoName + ") failed", e);
        }
        List<VXKmsKey> vXKeys = new ArrayList<VXKmsKey>();
        VXKmsKeyList vxKmsKeyList = new VXKmsKeyList();
        List<String> keys = null;
        String connProvider = null;
        boolean isKerberos = false;
        try {
            isKerberos = checkKerberos();
        } catch (Exception e1) {
            logger.error("checkKerberos(" + repoName + ") failed", e1);
        }
        if (providers != null) {
            for (int i = 0; i < providers.length; i++) {
                Client c = getClient();
                String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
                String keyLists = KMS_KEY_LIST_URI.replaceAll(Pattern.quote("${userName}"), currentUserLoginId);
                connProvider = providers[i];
                String uri = providers[i] + (providers[i].endsWith("/") ? keyLists : ("/" + keyLists));
                if (!isKerberos) {
                    uri = uri.concat("?user.name=" + currentUserLoginId);
                } else {
                    uri = uri.concat("?doAs=" + currentUserLoginId);
                }
                final WebResource r = c.resource(uri);
                try {
                    String response = null;
                    if (!isKerberos) {
                        response = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE)
                                .get(String.class);
                    } else {
                        Subject sub = getSubjectForKerberos(repoName);
                        response = Subject.doAs(sub, new PrivilegedAction<String>() {
                            @Override
                            public String run() {
                                return r.accept(MediaType.APPLICATION_JSON_TYPE)
                                        .type(MediaType.APPLICATION_JSON_TYPE).get(String.class);
                            }
                        });
                    }
                    Gson gson = new GsonBuilder().create();
                    logger.debug(" Search Key RESPONSE: [" + response + "]");
                    keys = gson.fromJson(response, List.class);
                    Collections.sort(keys);
                    VXKmsKeyList vxKmsKeyList2 = new VXKmsKeyList();
                    List<VXKmsKey> vXKeys2 = new ArrayList<VXKmsKey>();
                    for (String name : keys) {
                        VXKmsKey key = new VXKmsKey();
                        key.setName(name);
                        vXKeys2.add(key);
                    }
                    vxKmsKeyList2.setVXKeys(vXKeys2);
                    vxKmsKeyList = getFilteredKeyList(request, vxKmsKeyList2);
                    break;
                } catch (Exception e) {
                    if (e instanceof UniformInterfaceException || i == providers.length - 1)
                        throw e;
                    else
                        continue;
                }
            }
        }
        //details
        if (vxKmsKeyList != null && vxKmsKeyList.getVXKeys() != null && vxKmsKeyList.getVXKeys().size() > 0) {
            List<VXKmsKey> lstKMSKey = vxKmsKeyList.getVXKeys();
            int startIndex = restErrorUtil.parseInt(request.getParameter("startIndex"), 0,
                    "Invalid value for parameter startIndex", MessageEnums.INVALID_INPUT_DATA, null, "startIndex");
            startIndex = startIndex < 0 ? 0 : startIndex;

            int pageSize = restErrorUtil.parseInt(request.getParameter("pageSize"), 0,
                    "Invalid value for parameter pageSize", MessageEnums.INVALID_INPUT_DATA, null, "pageSize");
            pageSize = pageSize < 0 ? 0 : pageSize;

            vxKmsKeyList.setResultSize(lstKMSKey.size());
            vxKmsKeyList.setTotalCount(lstKMSKey.size());
            if ((startIndex + pageSize) <= lstKMSKey.size()) {
                lstKMSKey = lstKMSKey.subList(startIndex, (startIndex + pageSize));
            } else {
                startIndex = startIndex >= lstKMSKey.size() ? 0 : startIndex;
                lstKMSKey = lstKMSKey.subList(startIndex, lstKMSKey.size());
            }
            if (CollectionUtils.isNotEmpty(lstKMSKey)) {
                for (VXKmsKey kmsKey : lstKMSKey) {
                    if (kmsKey != null) {
                        VXKmsKey key = getKeyFromUri(connProvider, kmsKey.getName(), isKerberos, repoName);
                        vXKeys.add(key);
                    }
                }
            }
            vxKmsKeyList.setStartIndex(startIndex);
            vxKmsKeyList.setPageSize(pageSize);
        }
        if (vxKmsKeyList != null) {
            vxKmsKeyList.setVXKeys(vXKeys);
        }
        return vxKmsKeyList;
    }

    public VXKmsKey rolloverKey(String provider, VXKmsKey vXKey) throws Exception {
        String providers[] = null;
        try {
            providers = getKMSURL(provider);
        } catch (Exception e) {
            logger.error("rolloverKey(" + provider + ", " + vXKey.getName() + ") failed", e);
        }
        VXKmsKey ret = null;
        boolean isKerberos = false;
        try {
            isKerberos = checkKerberos();
        } catch (Exception e1) {
            logger.error("checkKerberos(" + provider + ") failed", e1);
        }
        if (providers != null) {
            for (int i = 0; i < providers.length; i++) {
                Client c = getClient();
                String rollRest = KMS_ROLL_KEY_URI.replaceAll(Pattern.quote("${alias}"), vXKey.getName());
                String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
                String uri = providers[i] + (providers[i].endsWith("/") ? rollRest : ("/" + rollRest));
                if (!isKerberos) {
                    uri = uri.concat("?user.name=" + currentUserLoginId);
                } else {
                    uri = uri.concat("?doAs=" + currentUserLoginId);
                }
                final WebResource r = c.resource(uri);
                Gson gson = new GsonBuilder().create();
                final String jsonString = gson.toJson(vXKey);
                try {
                    String response = null;
                    if (!isKerberos) {
                        response = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE)
                                .post(String.class, jsonString);
                    } else {
                        Subject sub = getSubjectForKerberos(provider);
                        response = Subject.doAs(sub, new PrivilegedAction<String>() {
                            @Override
                            public String run() {
                                return r.accept(MediaType.APPLICATION_JSON_TYPE)
                                        .type(MediaType.APPLICATION_JSON_TYPE).post(String.class, jsonString);
                            }
                        });
                    }
                    logger.debug("Roll RESPONSE: [" + response + "]");
                    ret = gson.fromJson(response, VXKmsKey.class);
                    break;
                } catch (Exception e) {
                    if (e instanceof UniformInterfaceException || i == providers.length - 1)
                        throw e;
                    else
                        continue;
                }
            }
        }
        return ret;
    }

    public void deleteKey(String provider, String name) throws Exception {
        String providers[] = null;
        try {
            providers = getKMSURL(provider);
        } catch (Exception e) {
            logger.error("deleteKey(" + provider + ", " + name + ") failed", e);
        }
        boolean isKerberos = false;
        try {
            isKerberos = checkKerberos();
        } catch (Exception e1) {
            logger.error("checkKerberos(" + provider + ") failed", e1);
        }
        if (providers != null) {
            for (int i = 0; i < providers.length; i++) {
                Client c = getClient();
                String deleteRest = KMS_DELETE_KEY_URI.replaceAll(Pattern.quote("${alias}"), name);
                String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
                String uri = providers[i] + (providers[i].endsWith("/") ? deleteRest : ("/" + deleteRest));
                if (!isKerberos) {
                    uri = uri.concat("?user.name=" + currentUserLoginId);
                } else {
                    uri = uri.concat("?doAs=" + currentUserLoginId);
                }
                final WebResource r = c.resource(uri);
                try {
                    String response = null;
                    if (!isKerberos) {
                        response = r.delete(String.class);
                    } else {
                        Subject sub = getSubjectForKerberos(provider);
                        response = Subject.doAs(sub, new PrivilegedAction<String>() {
                            @Override
                            public String run() {
                                return r.delete(String.class);
                            }
                        });
                    }
                    logger.debug("delete RESPONSE: [" + response + "]");
                    break;
                } catch (Exception e) {
                    if (e instanceof UniformInterfaceException || i == providers.length - 1)
                        throw e;
                    else
                        continue;
                }
            }
        }
    }

    public VXKmsKey createKey(String provider, VXKmsKey vXKey) throws Exception {
        String providers[] = null;
        try {
            providers = getKMSURL(provider);
        } catch (Exception e) {
            logger.error("createKey(" + provider + ", " + vXKey.getName() + ") failed", e);
        }
        VXKmsKey ret = null;
        boolean isKerberos = false;
        try {
            isKerberos = checkKerberos();
        } catch (Exception e1) {
            logger.error("checkKerberos(" + provider + ") failed", e1);
        }
        if (providers != null) {
            for (int i = 0; i < providers.length; i++) {
                Client c = getClient();
                String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
                String uri = providers[i]
                        + (providers[i].endsWith("/") ? KMS_ADD_KEY_URI : ("/" + KMS_ADD_KEY_URI));
                if (!isKerberos) {
                    uri = uri.concat("?user.name=" + currentUserLoginId);
                } else {
                    uri = uri.concat("?doAs=" + currentUserLoginId);
                }
                final WebResource r = c.resource(uri);
                Gson gson = new GsonBuilder().create();
                final String jsonString = gson.toJson(vXKey);
                try {
                    String response = null;
                    if (!isKerberos) {
                        response = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE)
                                .post(String.class, jsonString);
                    } else {
                        Subject sub = getSubjectForKerberos(provider);
                        response = Subject.doAs(sub, new PrivilegedAction<String>() {
                            @Override
                            public String run() {
                                return r.accept(MediaType.APPLICATION_JSON_TYPE)
                                        .type(MediaType.APPLICATION_JSON_TYPE).post(String.class, jsonString);
                            }
                        });
                    }
                    logger.debug("Create RESPONSE: [" + response + "]");
                    ret = gson.fromJson(response, VXKmsKey.class);
                    return ret;
                } catch (Exception e) {
                    if (e instanceof UniformInterfaceException || i == providers.length - 1)
                        throw e;
                    else
                        continue;
                }
            }
        }
        return ret;
    }

    public VXKmsKey getKey(String provider, String name) throws Exception {
        String providers[] = null;
        try {
            providers = getKMSURL(provider);
        } catch (Exception e) {
            logger.error("getKey(" + provider + ", " + name + ") failed", e);
        }
        boolean isKerberos = false;
        try {
            isKerberos = checkKerberos();
        } catch (Exception e1) {
            logger.error("checkKerberos(" + provider + ") failed", e1);
        }
        if (providers != null) {
            for (int i = 0; i < providers.length; i++) {
                Client c = getClient();
                String keyRest = KMS_KEY_METADATA_URI.replaceAll(Pattern.quote("${alias}"), name);
                String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
                String uri = providers[i] + (providers[i].endsWith("/") ? keyRest : ("/" + keyRest));
                if (!isKerberos) {
                    uri = uri.concat("?user.name=" + currentUserLoginId);
                } else {
                    uri = uri.concat("?doAs=" + currentUserLoginId);
                }
                final WebResource r = c.resource(uri);
                try {
                    String response = null;
                    if (!isKerberos) {
                        response = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE)
                                .get(String.class);
                    } else {
                        Subject sub = getSubjectForKerberos(provider);
                        response = Subject.doAs(sub, new PrivilegedAction<String>() {
                            @Override
                            public String run() {
                                return r.accept(MediaType.APPLICATION_JSON_TYPE)
                                        .type(MediaType.APPLICATION_JSON_TYPE).get(String.class);
                            }
                        });
                    }
                    Gson gson = new GsonBuilder().create();
                    logger.debug("RESPONSE: [" + response + "]");
                    VXKmsKey key = gson.fromJson(response, VXKmsKey.class);
                    return key;
                } catch (Exception e) {
                    if (e instanceof UniformInterfaceException || i == providers.length - 1)
                        throw e;
                    else
                        continue;
                }
            }
        }
        return null;
    }

    public VXKmsKey getKeyFromUri(String provider, String name, boolean isKerberos, String repoName)
            throws Exception {
        Client c = getClient();
        String keyRest = KMS_KEY_METADATA_URI.replaceAll(Pattern.quote("${alias}"), name);
        String currentUserLoginId = ContextUtil.getCurrentUserLoginId();
        String uri = provider + (provider.endsWith("/") ? keyRest : ("/" + keyRest));
        if (!isKerberos) {
            uri = uri.concat("?user.name=" + currentUserLoginId);
        } else {
            uri = uri.concat("?doAs=" + currentUserLoginId);
        }
        final WebResource r = c.resource(uri);
        String response = null;
        if (!isKerberos) {
            response = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE)
                    .get(String.class);
        } else {
            Subject sub = getSubjectForKerberos(repoName);
            response = Subject.doAs(sub, new PrivilegedAction<String>() {
                @Override
                public String run() {
                    return r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON_TYPE)
                            .get(String.class);
                }
            });
        }
        Gson gson = new GsonBuilder().create();
        logger.debug("RESPONSE: [" + response + "]");
        VXKmsKey key = gson.fromJson(response, VXKmsKey.class);
        return key;
    }

    private String[] getKMSURL(String name) throws Exception {
        String providers[] = null;
        RangerService rangerService = null;
        try {
            rangerService = svcStore.getServiceByName(name);
            if (rangerService != null) {
                String kmsUrl = rangerService.getConfigs().get(KMS_URL_CONFIG);
                String dbKmsUrl = kmsUrl;
                if (providerList.containsKey(kmsUrl)) {
                    kmsUrl = providerList.get(kmsUrl);
                } else {
                    providerList.put(kmsUrl, kmsUrl);
                }
                providers = createProvider(dbKmsUrl, kmsUrl);
            } else {
                throw new Exception("Service " + name + " not found");
            }
        } catch (Exception excp) {
            logger.error("getServiceByName(" + name + ") failed", excp);
            throw new Exception("getServiceByName(" + name + ") failed", excp);
        }
        if (providers == null) {
            throw new Exception("Providers for service " + name + " not found");
        }
        return providers;
    }

    private String[] createProvider(String dbKmsUrl, String uri) throws IOException, URISyntaxException {
        URI providerUri = new URI(uri);
        URL origUrl = new URL(extractKMSPath(providerUri).toString());
        String authority = origUrl.getAuthority();
        //    check for ';' which delimits the backup hosts
        if (Strings.isNullOrEmpty(authority)) {
            throw new IOException("No valid authority in kms uri [" + origUrl + "]");
        }
        //    Check if port is present in authority
        //    In the current scheme, all hosts have to run on the same port
        int port = -1;
        String hostsPart = authority;
        if (authority.contains(":")) {
            String[] t = authority.split(":");
            try {
                port = Integer.parseInt(t[1]);
            } catch (Exception e) {
                throw new IOException("Could not parse port in kms uri [" + origUrl + "]");
            }
            hostsPart = t[0];
        }
        return createProvider(dbKmsUrl, providerUri, origUrl, port, hostsPart);
    }

    private static Path extractKMSPath(URI uri) throws MalformedURLException, IOException {
        return ProviderUtils.unnestUri(uri);
    }

    private String[] createProvider(String dbkmsUrl, URI providerUri, URL origUrl, int port, String hostsPart)
            throws IOException {
        String[] hosts = hostsPart.split(";");
        String[] providers = new String[hosts.length];
        if (hosts.length == 1) {
            providers[0] = origUrl.toString();
        } else {
            String providerNext = providerUri.getScheme() + "://" + origUrl.getProtocol() + "@";
            for (int i = nextProvider; i < hosts.length; i++) {
                providerNext = providerNext + hosts[i];
                if (i != (hosts.length - 1)) {
                    providerNext = providerNext + ";";
                }
            }
            for (int i = 0; i < nextProvider && i < hosts.length; i++) {
                providerNext = providerNext + ";" + hosts[i];
            }
            if (nextProvider != hosts.length - 1) {
                nextProvider = nextProvider + 1;
            } else {
                nextProvider = 0;
            }
            providerNext = providerNext + ":" + port + origUrl.getPath();
            providerList.put(dbkmsUrl, providerNext);
            for (int i = 0; i < hosts.length; i++) {
                try {
                    String url = origUrl.getProtocol() + "://" + hosts[i] + ":" + port + origUrl.getPath();
                    providers[i] = new URI(url).toString();
                } catch (URISyntaxException e) {
                    throw new IOException("Could not Prase KMS URL..", e);
                }
            }
        }
        return providers;
    }

    private Subject getSubjectForKerberos(String provider) throws Exception {
        String userName = getKMSUserName(provider);
        String password = getKMSPassword(provider);
        String nameRules = PropertiesUtil.getProperty(NAME_RULES);
        if (StringUtils.isEmpty(nameRules)) {
            KerberosName.setRules("DEFAULT");
        } else {
            KerberosName.setRules(nameRules);
        }
        Subject sub = new Subject();
        String rangerPrincipal = SecureClientLogin.getPrincipal(PropertiesUtil.getProperty(ADMIN_USER_PRINCIPAL),
                PropertiesUtil.getProperty(HOST_NAME));
        if (checkKerberos()) {
            if (SecureClientLogin.isKerberosCredentialExists(rangerPrincipal,
                    PropertiesUtil.getProperty(ADMIN_USER_KEYTAB))) {
                sub = SecureClientLogin.loginUserFromKeytab(rangerPrincipal,
                        PropertiesUtil.getProperty(ADMIN_USER_KEYTAB), nameRules);
            } else {
                sub = SecureClientLogin.loginUserWithPassword(userName, password);
            }
        } else {
            sub = SecureClientLogin.login(userName);
        }
        return sub;
    }

    private String getKMSPassword(String srvName) throws Exception {
        XXService rangerService = rangerDaoManagerBase.getXXService().findByName(srvName);
        XXServiceConfigMap xxConfigMap = rangerDaoManagerBase.getXXServiceConfigMap()
                .findByServiceAndConfigKey(rangerService.getId(), KMS_PASSWORD);
        String encryptedPwd = xxConfigMap.getConfigvalue();
        String pwd = PasswordUtils.decryptPassword(encryptedPwd);
        return pwd;
    }

    private String getKMSUserName(String srvName) throws Exception {
        RangerService rangerService = null;
        rangerService = svcStore.getServiceByName(srvName);
        return rangerService.getConfigs().get(KMS_USERNAME);
    }

    private boolean checkKerberos() throws Exception {
        if (PropertiesUtil.getProperty(RANGER_AUTH_TYPE, "simple").equalsIgnoreCase(KERBEROS_TYPE)) {
            return true;
        } else {
            return false;
        }
    }

    private synchronized Client getClient() {
        Client ret = null;
        ClientConfig cc = new DefaultClientConfig();
        cc.getProperties().put(ClientConfig.PROPERTY_FOLLOW_REDIRECTS, true);
        ret = Client.create(cc);
        return ret;
    }

    public VXKmsKeyList getFilteredKeyList(HttpServletRequest request, VXKmsKeyList vXKmsKeyList) {
        List<SortField> sortFields = new ArrayList<SortField>();
        sortFields.add(new SortField(KeySearchFilter.KEY_NAME, KeySearchFilter.KEY_NAME));

        KeySearchFilter filter = getKeySearchFilter(request, sortFields);

        Predicate pred = getPredicate(filter);

        if (pred != null) {
            CollectionUtils.filter(vXKmsKeyList.getVXKeys(), pred);
        }
        return vXKmsKeyList;
    }

    private Predicate getPredicate(KeySearchFilter filter) {
        if (filter == null || filter.isEmpty()) {
            return null;
        }

        List<Predicate> predicates = new ArrayList<Predicate>();

        addPredicateForKeyName(filter.getParam(KeySearchFilter.KEY_NAME), predicates);

        Predicate ret = CollectionUtils.isEmpty(predicates) ? null : PredicateUtils.allPredicate(predicates);

        return ret;
    }

    private Predicate addPredicateForKeyName(final String name, List<Predicate> predicates) {
        if (StringUtils.isEmpty(name)) {
            return null;
        }

        Predicate ret = new Predicate() {
            @Override
            public boolean evaluate(Object object) {
                if (object == null) {
                    return false;
                }

                boolean ret = false;

                if (object instanceof VXKmsKey) {
                    VXKmsKey vXKmsKey = (VXKmsKey) object;
                    if (StringUtils.isEmpty(vXKmsKey.getName())) {
                        ret = true;
                    } else {
                        ret = vXKmsKey.getName().contains(name);
                    }
                } else {
                    ret = true;
                }

                return ret;
            }
        };

        if (predicates != null) {
            predicates.add(ret);
        }

        return ret;
    }

    private KeySearchFilter getKeySearchFilter(HttpServletRequest request, List<SortField> sortFields) {
        if (request == null) {
            return null;
        }
        KeySearchFilter ret = new KeySearchFilter();

        if (MapUtils.isEmpty(request.getParameterMap())) {
            ret.setParams(new HashMap<String, String>());
        }

        ret.setParam(KeySearchFilter.KEY_NAME, request.getParameter(KeySearchFilter.KEY_NAME));
        extractCommonCriteriasForFilter(request, ret, sortFields);
        return ret;
    }

    private KeySearchFilter extractCommonCriteriasForFilter(HttpServletRequest request, KeySearchFilter ret,
            List<SortField> sortFields) {
        int startIndex = restErrorUtil.parseInt(request.getParameter(KeySearchFilter.START_INDEX), 0,
                "Invalid value for parameter startIndex", MessageEnums.INVALID_INPUT_DATA, null,
                KeySearchFilter.START_INDEX);
        ret.setStartIndex(startIndex);

        int pageSize = restErrorUtil.parseInt(request.getParameter(KeySearchFilter.PAGE_SIZE),
                configUtil.getDefaultMaxRows(), "Invalid value for parameter pageSize",
                MessageEnums.INVALID_INPUT_DATA, null, KeySearchFilter.PAGE_SIZE);
        ret.setMaxRows(pageSize);

        ret.setGetCount(restErrorUtil.parseBoolean(request.getParameter("getCount"), true));
        String sortBy = restErrorUtil.validateString(request.getParameter(KeySearchFilter.SORT_BY),
                StringUtil.VALIDATION_ALPHA, "Invalid value for parameter sortBy", MessageEnums.INVALID_INPUT_DATA,
                null, KeySearchFilter.SORT_BY);
        boolean sortSet = false;
        if (!StringUtils.isEmpty(sortBy)) {
            for (SortField sortField : sortFields) {
                if (sortField.getParamName().equalsIgnoreCase(sortBy)) {
                    ret.setSortBy(sortField.getParamName());
                    String sortType = restErrorUtil.validateString(request.getParameter("sortType"),
                            StringUtil.VALIDATION_ALPHA, "Invalid value for parameter sortType",
                            MessageEnums.INVALID_INPUT_DATA, null, "sortType");
                    ret.setSortType(sortType);
                    sortSet = true;
                    break;
                }
            }
        }

        if (!sortSet && !StringUtils.isEmpty(sortBy)) {
            logger.info("Invalid or unsupported sortBy field passed. sortBy=" + sortBy, new Throwable());
        }

        if (ret.getParams() == null) {
            ret.setParams(new HashMap<String, String>());
        }
        return ret;
    }
}