Java tutorial
/** * Copyright (C) 2015 Distributed Search, Inc. * * Licensed 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 com.kibana.multitenancy.plugin; import java.nio.charset.StandardCharsets; import javax.xml.bind.DatatypeConverter; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang.StringUtils; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.logging.ESLogger; import org.jboss.netty.buffer.BigEndianHeapChannelBuffer; import org.jboss.netty.handler.codec.http.HttpRequest; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.http.netty.NettyHttpRequest; import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestFilter; import org.elasticsearch.rest.RestFilterChain; import org.elasticsearch.rest.RestRequest; import com.petalmd.armor.authentication.AuthCredentials; import com.petalmd.armor.authentication.AuthException; import com.petalmd.armor.authentication.User; public class KibanaUserReindexFilter extends RestFilter implements ConfigurationSettings { private final ESLogger logger; private final String proxyUserHeader; private final String kibanaIndex; public KibanaUserReindexFilter(final Settings settings, final ESLogger logger) { this.logger = logger; //This need to be changed as per HAProxy Header this.proxyUserHeader = settings.get(ARMOR_AUTHENTICATION_PROXY_HEADER, DEFAULT_AUTH_PROXY_HEADER); this.kibanaIndex = settings.get(KIBANA_CONFIG_INDEX_NAME, DEFAULT_USER_PROFILE_PREFIX); } @Override public void process(RestRequest request, RestChannel channel, RestFilterChain chain) throws Exception { try { logger.debug("Handling Request in Kibana User Reindex filter..."); final String user = getUser(request); final String requestedIndex = getRequestedIndex(request); logger.debug("Received user '{}' and index '{}', looking for index '{}'", user, requestedIndex, kibanaIndex); if (StringUtils.isNotEmpty(user) && StringUtils.isNotEmpty(requestedIndex) && requestedIndex.equalsIgnoreCase(kibanaIndex)) { String userIndex = requestedIndex + "." + getUsernameHash(user); logger.debug("Matched for a kibana user header, will set to '{}' for user '{}'", userIndex, user); //update the request URI here request = updateRequestIndex(request, requestedIndex, userIndex); logger.debug("URI for request is '{}' after update", request.uri()); } else { if (StringUtils.isNotEmpty(user) && StringUtils.isNotEmpty(requestedIndex) && requestedIndex.startsWith("_mget")) { String userIndex = ".kibana." + getUsernameHash(user); logger.debug("Matched for a kibana user header, will set to '{}' for user '{}'", userIndex, user); //update the request URI here request = updateMGetRequest(request, ".kibana", userIndex); logger.debug("URI for request is '{}' after update", request.uri()); } } } catch (Exception e) { logger.error("Error handling request in Iaas armor filter", e); } finally { chain.continueProcessing(request, channel); } } /*As Authentication happens in Armor so This Filter should run at the end after ARMOR * using the order function*/ private String getUser(RestRequest request) { //Sushant:Getting user in case of Basic Authentication String username = ""; //Sushant:Scenario when user Authenticated at Proxy level itself String proxyAuthUser = StringUtils.defaultIfBlank(request.header(proxyUserHeader), ""); //Sushant: Scenario when user Authenticated at Proxy level itself String basicAuthorizationHeader = StringUtils.defaultIfBlank(request.header("Authorization"), ""); if (StringUtils.isNotEmpty(basicAuthorizationHeader)) { String decodedBasicHeader = new String( DatatypeConverter.parseBase64Binary(basicAuthorizationHeader.split(" ")[1]), StandardCharsets.US_ASCII); final String[] decodedBasicHeaderParts = decodedBasicHeader.split(":"); username = decodedBasicHeaderParts[0]; decodedBasicHeader = null; basicAuthorizationHeader = null; logger.debug("User '{}' is authenticated", username); } return username; } private RestRequest updateMGetRequest(RestRequest request, String oldIndex, String newIndex) { BytesReference content = request.content(); String stringContent = content.toUtf8(); logger.debug("Received MGet request '{}' with content '{}'", request, stringContent); String replaced = stringContent.replaceAll("_index\":\"" + oldIndex + "\"", "_index\":\"" + newIndex + "\""); NettyHttpRequest nettyRequest = (NettyHttpRequest) request; HttpRequest httpRequest = nettyRequest.request(); BytesReference replacedContent = new BytesArray(replaced); BigEndianHeapChannelBuffer buffer = new BigEndianHeapChannelBuffer(replacedContent.array()); httpRequest.setContent(buffer); return new NettyHttpRequest(httpRequest, nettyRequest.getChannel()); } private RestRequest updateRequestIndex(RestRequest request, String oldIndex, String newIndex) { String uri = request.uri(); String replaced = uri.replace(oldIndex, newIndex); NettyHttpRequest nettyRequest = (NettyHttpRequest) request; HttpRequest httpRequest = nettyRequest.request(); httpRequest.setUri(replaced); return new NettyHttpRequest(httpRequest, nettyRequest.getChannel()); } private String getRequestedIndex(RestRequest request) { String uri = StringUtils.defaultIfBlank(request.uri(), ""); String[] splitUri = uri.split("/"); if (splitUri.length > 0) return uri.split("/")[1]; else return ""; } @Override public int order() { // need to run last return Integer.MAX_VALUE; } public static String getUsernameHash(String username) { return DigestUtils.sha1Hex(username); } }