Skip to content

Commit

Permalink
Merge branch 'dev-2305' into dev-1.8
Browse files Browse the repository at this point in the history
# Conflicts:
#	.github/workflows/ci.yml
#	.github/workflows/codeql-analysis.yml
#	doc/awesome-sentinel.md
#	pom.xml
#	sentinel-adapter/pom.xml
#	sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml
#	sentinel-adapter/sentinel-apache-dubbo3-adapter/pom.xml
#	sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml
#	sentinel-adapter/sentinel-api-gateway-adapter-common/pom.xml
#	sentinel-adapter/sentinel-dubbo-adapter/pom.xml
#	sentinel-adapter/sentinel-grpc-adapter/pom.xml
#	sentinel-adapter/sentinel-jax-rs-adapter/pom.xml
#	sentinel-adapter/sentinel-motan-adapter/pom.xml
#	sentinel-adapter/sentinel-okhttp-adapter/pom.xml
#	sentinel-adapter/sentinel-quarkus-adapter/pom.xml
#	sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/pom.xml
#	sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/pom.xml
#	sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/pom.xml
#	sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/pom.xml
#	sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/pom.xml
#	sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/pom.xml
#	sentinel-adapter/sentinel-reactor-adapter/pom.xml
#	sentinel-adapter/sentinel-sofa-rpc-adapter/pom.xml
#	sentinel-adapter/sentinel-spring-cloud-gateway-adapter/pom.xml
#	sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml
#	sentinel-adapter/sentinel-spring-webmvc-adapter/pom.xml
#	sentinel-adapter/sentinel-web-servlet/pom.xml
#	sentinel-adapter/sentinel-zuul-adapter/pom.xml
#	sentinel-adapter/sentinel-zuul2-adapter/pom.xml
#	sentinel-benchmark/pom.xml
#	sentinel-cluster/pom.xml
#	sentinel-cluster/sentinel-cluster-client-default/pom.xml
#	sentinel-cluster/sentinel-cluster-common-default/pom.xml
#	sentinel-cluster/sentinel-cluster-server-default/pom.xml
#	sentinel-cluster/sentinel-cluster-server-envoy-rls/pom.xml
#	sentinel-core/pom.xml
#	sentinel-core/src/main/java/com/alibaba/csp/sentinel/Constants.java
#	sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/degrade/CircuitBreakingIntegrationTest.java
#	sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/tokenbucket/TokenBucketTest.java
#	sentinel-dashboard/Dockerfile
#	sentinel-dashboard/README.md
#	sentinel-dashboard/pom.xml
#	sentinel-demo/pom.xml
#	sentinel-demo/sentinel-demo-annotation-cdi-interceptor/pom.xml
#	sentinel-demo/sentinel-demo-annotation-spring-aop/pom.xml
#	sentinel-demo/sentinel-demo-apache-dubbo/pom.xml
#	sentinel-demo/sentinel-demo-apache-httpclient/pom.xml
#	sentinel-demo/sentinel-demo-apollo-datasource/pom.xml
#	sentinel-demo/sentinel-demo-basic/pom.xml
#	sentinel-demo/sentinel-demo-cluster/pom.xml
#	sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml
#	sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml
#	sentinel-demo/sentinel-demo-command-handler/pom.xml
#	sentinel-demo/sentinel-demo-dubbo/pom.xml
#	sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml
#	sentinel-demo/sentinel-demo-etcd-datasource/pom.xml
#	sentinel-demo/sentinel-demo-jax-rs/pom.xml
#	sentinel-demo/sentinel-demo-log-logback/pom.xml
#	sentinel-demo/sentinel-demo-motan/pom.xml
#	sentinel-demo/sentinel-demo-nacos-datasource/pom.xml
#	sentinel-demo/sentinel-demo-okhttp/pom.xml
#	sentinel-demo/sentinel-demo-parameter-flow-control/pom.xml
#	sentinel-demo/sentinel-demo-quarkus/pom.xml
#	sentinel-demo/sentinel-demo-rocketmq/pom.xml
#	sentinel-demo/sentinel-demo-slot-spi/pom.xml
#	sentinel-demo/sentinel-demo-slotchain-spi/pom.xml
#	sentinel-demo/sentinel-demo-sofa-rpc/pom.xml
#	sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml
#	sentinel-demo/sentinel-demo-spring-webflux/pom.xml
#	sentinel-demo/sentinel-demo-spring-webmvc/pom.xml
#	sentinel-demo/sentinel-demo-transport-spring-mvc/pom.xml
#	sentinel-demo/sentinel-demo-zookeeper-datasource/pom.xml
#	sentinel-demo/sentinel-demo-zuul-gateway/pom.xml
#	sentinel-demo/sentinel-demo-zuul2-gateway/pom.xml
#	sentinel-extension/pom.xml
#	sentinel-extension/sentinel-annotation-aspectj/pom.xml
#	sentinel-extension/sentinel-annotation-cdi-interceptor/pom.xml
#	sentinel-extension/sentinel-datasource-apollo/pom.xml
#	sentinel-extension/sentinel-datasource-consul/pom.xml
#	sentinel-extension/sentinel-datasource-etcd/pom.xml
#	sentinel-extension/sentinel-datasource-eureka/pom.xml
#	sentinel-extension/sentinel-datasource-extension/pom.xml
#	sentinel-extension/sentinel-datasource-nacos/pom.xml
#	sentinel-extension/sentinel-datasource-redis/pom.xml
#	sentinel-extension/sentinel-datasource-spring-cloud-config/pom.xml
#	sentinel-extension/sentinel-datasource-zookeeper/pom.xml
#	sentinel-extension/sentinel-metric-exporter/pom.xml
#	sentinel-extension/sentinel-parameter-flow-control/pom.xml
#	sentinel-extension/sentinel-parameter-flow-control/src/test/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowPartialIntegrationTest.java
#	sentinel-extension/sentinel-prometheus-metric-exporter/pom.xml
#	sentinel-logging/pom.xml
#	sentinel-logging/sentinel-logging-slf4j/pom.xml
#	sentinel-transport/pom.xml
#	sentinel-transport/sentinel-transport-common/pom.xml
#	sentinel-transport/sentinel-transport-netty-http/pom.xml
#	sentinel-transport/sentinel-transport-simple-http/pom.xml
#	sentinel-transport/sentinel-transport-spring-mvc/pom.xml
  • Loading branch information
luffy0223 committed Apr 23, 2024
2 parents cd02b1d + 2d36940 commit a91ab87
Show file tree
Hide file tree
Showing 168 changed files with 15,622 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* 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
*
* https://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.alibaba.csp.sentinel.adapter.spring.webmvc;

import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.trust.TrustManager;
import com.alibaba.csp.sentinel.trust.tls.TlsMode;
import com.alibaba.csp.sentinel.trust.validator.AuthValidator;
import com.alibaba.csp.sentinel.trust.validator.UnifiedHttpRequest;
import com.alibaba.csp.sentinel.util.StringUtil;

import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.HandlerInterceptor;

/**
* @author lwj
* @since 2.0.0
*/
public class SentinelTrustInterceptor implements HandlerInterceptor {

private static final String UNKNOWN_IP = "unknown";
private TrustManager trustManager = TrustManager.getInstance();

public static String getPrincipal(X509Certificate x509Certificate) {
try {
Collection<List<?>> san = x509Certificate.getSubjectAlternativeNames();
return (String) san.iterator().next().get(1);
} catch (Exception e) {
RecordLog.error("Failed to get istio SAN from X509Certificate", e);
}
return null;
}

public static String getRemoteIpAddress(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
//Only select the first one
if (StringUtil.isNotEmpty(ip) && !UNKNOWN_IP.equalsIgnoreCase(ip)) {
if (ip.contains(",")) {
ip = ip.split(",")[0];
return ip;
}
}
if (null != request.getRemoteAddr()) {
return request.getRemoteAddr();
}
return null;
}

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (null == trustManager.getTlsMode()) {
return true;
}
//Don't authenticate in DISABLE mode
int port = request.getLocalPort();
TlsMode tlsMode = trustManager.getTlsMode();
TlsMode.TlsType currentTlsType = tlsMode.getPortTls(port);
if (TlsMode.TlsType.DISABLE == currentTlsType) {
return true;
}

X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
boolean notHaveCert = (null == certs || 0 == certs.length);
//When no cert,don't authenticate in PERMISSIVE mode
if (notHaveCert) {
if (TlsMode.TlsType.STRICT == currentTlsType) {
return false;
}

if (TlsMode.TlsType.PERMISSIVE == currentTlsType) {
return true;
}
}

if (null == trustManager.getRules()) {
return true;
}

String principal = getPrincipal(certs[0]);
String sourceIp = request.getRemoteAddr();
String destIp = request.getLocalAddr();
String remoteIp = getRemoteIpAddress(request);
String host = request.getHeader(HttpHeaders.HOST);
String method = request.getMethod();
String path = request.getRequestURI();
Map<String, List<String>> headers = getHeaders(request);
Map<String, List<String>> params = getParams(request);
String sni = request.getServerName();

UnifiedHttpRequest.UnifiedHttpRequestBuilder builder = new UnifiedHttpRequest.UnifiedHttpRequestBuilder();
UnifiedHttpRequest unifiedHttpRequest = builder
.setDestIp(destIp)
.setRemoteIp(remoteIp)
.setSourceIp(sourceIp)
.setHost(host)
.setPort(port)
.setMethod(method)
.setPath(path)
.setHeaders(headers)
.setParams(params)
.setPrincipal(principal)
.setSni(sni)
.build();

return AuthValidator.validate(unifiedHttpRequest, trustManager.getRules());
}

private Map<String, List<String>> getHeaders(HttpServletRequest request) {
Map<String, List<String>> headers = new HashMap<>();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key = headerNames.nextElement();
Enumeration<String> headerValues = request.getHeaders(key);
List<String> values = new ArrayList<>();
while (headerValues.hasMoreElements()) {
values.add(headerValues.nextElement());
}
headers.put(key, values);

}
return headers;
}

private Map<String, List<String>> getParams(HttpServletRequest request) {
Map<String, List<String>> params = new HashMap<>();
Enumeration<String> paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String key = paramNames.nextElement();
List<String> values = Arrays.asList(request.getParameterValues(key));
params.put(key, values);
}
return params;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.fallback;

import java.lang.reflect.Method;

/**
* Annotation global fallback interface
*
* @author luffy
*/
public interface SentinelAnnotationGlobalFallback {

/**
*
* @param originalMethod the original method called
* @param args The parameters of the method that was originally called
* @param t The exception thrown by the method originally called
* @return The result of the global fallback handler execution
* @throws Throwable
*/
Object handle(Method originalMethod, Object[] args, Throwable t) throws Throwable;

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ class DateFileLogHandler extends Handler {
executor.allowCoreThreadTimeOut(true);
}

private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
1,
5,
1,
TimeUnit.HOURS,
new ArrayBlockingQueue<Runnable>(1024),
new NamedThreadFactory("sentinel-datafile-log-executor", true),
new ThreadPoolExecutor.DiscardOldestPolicy()
);

static {
// allow all thread could be stopped
executor.allowCoreThreadTimeOut(true);
}

private volatile FileHandler handler;

private final String pattern;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.traffic;

import java.util.List;

/**
* @author panxiaojun233
*/
public abstract class AbstractLoadBalancer implements LoadBalancer {
@Override
public Instance select(List<Instance> instances, TrafficContext trafficContext) throws TrafficException {
if (instances == null || instances.size() == 0) {
return null;
}
if (instances.size() == 1) {
return instances.get(0);
}
return doSelect(instances, trafficContext);
}

protected abstract Instance doSelect(List<Instance> instances, TrafficContext trafficContext);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* 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.alibaba.csp.sentinel.traffic;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.alibaba.csp.sentinel.traffic.rule.router.TrafficRouterRuleManager;

/**
* @author panxiaojun233
*/
public class ClusterManager implements InstanceListener {
private List<RouterFilter> routerFilterList;
private LoadBalancer loadBalancer;
private InstanceManager instanceManager;
private volatile Set<String> remoteAppName = Collections.emptySet();

public ClusterManager(List<RouterFilter> routerFilterList, LoadBalancer loadBalancer, InstanceManager instanceManager) {
this.routerFilterList = routerFilterList;
this.loadBalancer = loadBalancer;
this.instanceManager = instanceManager;
}

public Set<String> getRemoteAppName() {
return remoteAppName;
}

public ClusterManager(List<RouterFilter> routerFilterList) {
this.routerFilterList = routerFilterList;
}

public ClusterManager(InstanceManager instanceManager) {
this.instanceManager = instanceManager;
}

/**
* Select one invoker in list, routing first, then load balancing.
*
* @param context traffic context.
* @return selected instance.
*/
public Instance selectOneInstance(TrafficContext context) {
return loadBalancer.select(route(context), context);
}

/**
* Select one invoker in list.
*
* @param context traffic context.
* @param instances instance List.
* @return selected instance.
*/
public Instance loadBalance(TrafficContext context, List<Instance> instances) {
return loadBalancer.select(instances, context);
}

public Instance loadBalance(TrafficContext context) {
return loadBalancer.select(instanceManager.getInstances(), context);
}

/**
* Filter instances form instanceManager by current routing rule and traffic context.
*
* @param context traffic context
* @return instance List
*/
public List<Instance> route(TrafficContext context) {
List<Instance> instances = instanceManager.getInstances();
for (RouterFilter routerFilter : routerFilterList) {
instances = routerFilter.filter(instances, context);
}
return instances;
}

/**
* Register the application in the instance List.
*
* @param instances instance List
*/
private void registerAppRule(List<Instance> instances) {
Set<String> currentApplication = new HashSet<>();
if (instances != null && instances.size() > 0) {
for (Instance instance : instances) {
String applicationName = instance.getAppName();
if (applicationName != null && applicationName.length() > 0) {
currentApplication.add(applicationName);
}
}
}

if (!remoteAppName.equals(currentApplication)) {
synchronized (this) {
Set<String> current = new HashSet<>(currentApplication);
Set<String> previous = new HashSet<>(remoteAppName);
previous.removeAll(currentApplication);
current.removeAll(remoteAppName);
for (String app : current) {
TrafficRouterRuleManager.register(app);
}
for (String app : previous) {
TrafficRouterRuleManager.unregister(app);
}
remoteAppName = currentApplication;
}
}
}

@Override
public void notify(List<Instance> instances) {
registerAppRule(instances);
instanceManager.storeInstances(instances);
}
}
Loading

0 comments on commit a91ab87

Please sign in to comment.