Skip to content

Commit

Permalink
Merge pull request alibaba#3182: Add Sentinel 2.0 zero-trust basic im…
Browse files Browse the repository at this point in the history
…plementation

* Add fundamental building blocks for zero-trust (certificate manager, authentication) as part of the traffic governance module (流量治理-零信任模块实现)
  • Loading branch information
sczyh30 authored Aug 16, 2023
2 parents cb21446 + 7e8f539 commit d00798f
Show file tree
Hide file tree
Showing 105 changed files with 11,524 additions and 2 deletions.
9 changes: 7 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@

<modules>
<module>sentinel-core</module>
<module>sentinel-security-core</module>
<module>sentinel-extension</module>
<module>sentinel-transport</module>
<module>sentinel-adapter</module>
Expand All @@ -79,7 +80,6 @@

<module>sentinel-demo</module>
<module>sentinel-benchmark</module>

</modules>

<dependencyManagement>
Expand All @@ -89,6 +89,11 @@
<artifactId>sentinel-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-security-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-extension</artifactId>
Expand Down Expand Up @@ -170,7 +175,7 @@
<artifactId>sentinel-metric-exporter</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
Expand Down
5 changes: 5 additions & 0 deletions sentinel-adapter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
<artifactId>sentinel-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-security-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-extension</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions sentinel-adapter/sentinel-spring-webmvc-adapter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-security-core</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
Expand Down
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-2020 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.util;

import java.util.Collection;
import java.util.Map;

/**
* @author Eric Zhao
* @author lwj
* @since 2.0.0
*/
public final class CollectionUtil {

private CollectionUtil() {}

public static boolean isEmpty(Collection<?> c) {
return c == null || c.isEmpty();
}

public static boolean isEmpty(Map<?, ?> c) {
return c == null || c.isEmpty();
}
}
Loading

0 comments on commit d00798f

Please sign in to comment.