/*
* Copyright 2015 floragunn UG (haftungsbeschränkt)
*
* 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.floragunn.searchguard.http;
import java.net.InetSocketAddress;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.netty.NettyHttpRequest;
import org.elasticsearch.rest.RestRequest;
import com.floragunn.searchguard.action.configupdate.TransportConfigUpdateAction;
import com.floragunn.searchguard.configuration.ConfigChangeListener;
import com.floragunn.searchguard.support.ConfigConstants;
public class XFFResolver implements ConfigChangeListener {
protected final ESLogger log = Loggers.getLogger(this.getClass());
private volatile Settings settings;
private volatile boolean enabled;
private volatile RemoteIpDetector detector;
@Inject
public XFFResolver(final TransportConfigUpdateAction tcua) {
super();
tcua.addConfigChangeListener("config", this);
}
public TransportAddress resolve(final RestRequest request) throws ElasticsearchSecurityException {
if(log.isTraceEnabled()) {
log.trace("resolve {}", request.getRemoteAddress());
}
if(isInitialized() && enabled && request.getRemoteAddress() instanceof InetSocketAddress && request instanceof NettyHttpRequest) {
InetSocketAddress isa = new InetSocketAddress(detector.detect((NettyHttpRequest) request), ((InetSocketAddress)request.getRemoteAddress()).getPort());
if(isa.isUnresolved()) {
throw new ElasticsearchSecurityException("Cannot resolve address "+isa.getHostString());
}
if(log.isTraceEnabled()) {
if(request.getFromContext(ConfigConstants.SG_XFF_DONE) == Boolean.TRUE) {
log.trace("xff resolved {} to {}", request.getRemoteAddress(), isa);
} else {
log.trace("no xff done for {}",request.getClass());
}
}
return new InetSocketTransportAddress(isa);
} else if(request.getRemoteAddress() instanceof InetSocketAddress){
if(log.isTraceEnabled()) {
log.trace("no xff done (not initialized, enabled or no netty request) {},{},{},{}",isInitialized(), enabled, request.getClass());
}
return new InetSocketTransportAddress((InetSocketAddress)request.getRemoteAddress());
} else {
throw new ElasticsearchSecurityException("Cannot handle this request. Remote address is "+request.getRemoteAddress()+" with request class "+request.getClass());
}
}
@Override
public void onChange(String event, Settings settings) {
this.settings = settings;
enabled = settings.getAsBoolean("searchguard.dynamic.http.xff.enabled", true);
if(enabled) {
detector = new RemoteIpDetector();
detector.setInternalProxies(settings.get("searchguard.dynamic.http.xff.internalProxies", detector.getInternalProxies()));
detector.setProxiesHeader(settings.get("searchguard.dynamic.http.xff.proxiesHeader", detector.getProxiesHeader()));
detector.setRemoteIpHeader(settings.get("searchguard.dynamic.http.xff.remoteIpHeader", detector.getRemoteIpHeader()));
detector.setTrustedProxies(settings.get("searchguard.dynamic.http.xff.trustedProxies", detector.getTrustedProxies()));
} else {
detector = null;
}
}
@Override
public void validate(String event, Settings settings) throws ElasticsearchSecurityException {
}
@Override
public boolean isInitialized() {
return this.settings != null;
}
}