Skip to content

Commit d00798f

Browse files
authored
Merge pull request alibaba#3182: Add Sentinel 2.0 zero-trust basic implementation
* Add fundamental building blocks for zero-trust (certificate manager, authentication) as part of the traffic governance module (流量治理-零信任模块实现)
2 parents cb21446 + 7e8f539 commit d00798f

File tree

105 files changed

+11524
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+11524
-2
lines changed

pom.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969

7070
<modules>
7171
<module>sentinel-core</module>
72+
<module>sentinel-security-core</module>
7273
<module>sentinel-extension</module>
7374
<module>sentinel-transport</module>
7475
<module>sentinel-adapter</module>
@@ -79,7 +80,6 @@
7980

8081
<module>sentinel-demo</module>
8182
<module>sentinel-benchmark</module>
82-
8383
</modules>
8484

8585
<dependencyManagement>
@@ -89,6 +89,11 @@
8989
<artifactId>sentinel-core</artifactId>
9090
<version>${project.version}</version>
9191
</dependency>
92+
<dependency>
93+
<groupId>com.alibaba.csp</groupId>
94+
<artifactId>sentinel-security-core</artifactId>
95+
<version>${project.version}</version>
96+
</dependency>
9297
<dependency>
9398
<groupId>com.alibaba.csp</groupId>
9499
<artifactId>sentinel-extension</artifactId>
@@ -170,7 +175,7 @@
170175
<artifactId>sentinel-metric-exporter</artifactId>
171176
<version>${project.version}</version>
172177
</dependency>
173-
178+
174179
<dependency>
175180
<groupId>com.alibaba</groupId>
176181
<artifactId>fastjson</artifactId>

sentinel-adapter/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
<artifactId>sentinel-core</artifactId>
4343
<version>${project.version}</version>
4444
</dependency>
45+
<dependency>
46+
<groupId>com.alibaba.csp</groupId>
47+
<artifactId>sentinel-security-core</artifactId>
48+
<version>${project.version}</version>
49+
</dependency>
4550
<dependency>
4651
<groupId>com.alibaba.csp</groupId>
4752
<artifactId>sentinel-extension</artifactId>

sentinel-adapter/sentinel-spring-webmvc-adapter/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
<groupId>com.alibaba.csp</groupId>
2424
<artifactId>sentinel-core</artifactId>
2525
</dependency>
26+
<dependency>
27+
<groupId>com.alibaba.csp</groupId>
28+
<artifactId>sentinel-security-core</artifactId>
29+
</dependency>
2630
<dependency>
2731
<groupId>javax.servlet</groupId>
2832
<artifactId>javax.servlet-api</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright 1999-2023 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.spring.webmvc;
17+
18+
import java.security.cert.X509Certificate;
19+
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.Collection;
22+
import java.util.Enumeration;
23+
import java.util.HashMap;
24+
import java.util.List;
25+
import java.util.Map;
26+
27+
import javax.servlet.http.HttpServletRequest;
28+
import javax.servlet.http.HttpServletResponse;
29+
30+
import com.alibaba.csp.sentinel.log.RecordLog;
31+
import com.alibaba.csp.sentinel.trust.TrustManager;
32+
import com.alibaba.csp.sentinel.trust.tls.TlsMode;
33+
import com.alibaba.csp.sentinel.trust.validator.AuthValidator;
34+
import com.alibaba.csp.sentinel.trust.validator.UnifiedHttpRequest;
35+
import com.alibaba.csp.sentinel.util.StringUtil;
36+
37+
import org.springframework.http.HttpHeaders;
38+
import org.springframework.web.servlet.HandlerInterceptor;
39+
40+
/**
41+
* @author lwj
42+
* @since 2.0.0
43+
*/
44+
public class SentinelTrustInterceptor implements HandlerInterceptor {
45+
46+
private static final String UNKNOWN_IP = "unknown";
47+
private TrustManager trustManager = TrustManager.getInstance();
48+
49+
public static String getPrincipal(X509Certificate x509Certificate) {
50+
try {
51+
Collection<List<?>> san = x509Certificate.getSubjectAlternativeNames();
52+
return (String) san.iterator().next().get(1);
53+
} catch (Exception e) {
54+
RecordLog.error("Failed to get istio SAN from X509Certificate", e);
55+
}
56+
return null;
57+
}
58+
59+
public static String getRemoteIpAddress(HttpServletRequest request) {
60+
String ip = request.getHeader("X-Forwarded-For");
61+
//Only select the first one
62+
if (StringUtil.isNotEmpty(ip) && !UNKNOWN_IP.equalsIgnoreCase(ip)) {
63+
if (ip.contains(",")) {
64+
ip = ip.split(",")[0];
65+
return ip;
66+
}
67+
}
68+
if (null != request.getRemoteAddr()) {
69+
return request.getRemoteAddr();
70+
}
71+
return null;
72+
}
73+
74+
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
75+
throws Exception {
76+
if (null == trustManager.getTlsMode()) {
77+
return true;
78+
}
79+
//Don't authenticate in DISABLE mode
80+
int port = request.getLocalPort();
81+
TlsMode tlsMode = trustManager.getTlsMode();
82+
TlsMode.TlsType currentTlsType = tlsMode.getPortTls(port);
83+
if (TlsMode.TlsType.DISABLE == currentTlsType) {
84+
return true;
85+
}
86+
87+
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
88+
boolean notHaveCert = (null == certs || 0 == certs.length);
89+
//When no cert,don't authenticate in PERMISSIVE mode
90+
if (notHaveCert) {
91+
if (TlsMode.TlsType.STRICT == currentTlsType) {
92+
return false;
93+
}
94+
95+
if (TlsMode.TlsType.PERMISSIVE == currentTlsType) {
96+
return true;
97+
}
98+
}
99+
100+
if (null == trustManager.getRules()) {
101+
return true;
102+
}
103+
104+
String principal = getPrincipal(certs[0]);
105+
String sourceIp = request.getRemoteAddr();
106+
String destIp = request.getLocalAddr();
107+
String remoteIp = getRemoteIpAddress(request);
108+
String host = request.getHeader(HttpHeaders.HOST);
109+
String method = request.getMethod();
110+
String path = request.getRequestURI();
111+
Map<String, List<String>> headers = getHeaders(request);
112+
Map<String, List<String>> params = getParams(request);
113+
String sni = request.getServerName();
114+
115+
UnifiedHttpRequest.UnifiedHttpRequestBuilder builder = new UnifiedHttpRequest.UnifiedHttpRequestBuilder();
116+
UnifiedHttpRequest unifiedHttpRequest = builder
117+
.setDestIp(destIp)
118+
.setRemoteIp(remoteIp)
119+
.setSourceIp(sourceIp)
120+
.setHost(host)
121+
.setPort(port)
122+
.setMethod(method)
123+
.setPath(path)
124+
.setHeaders(headers)
125+
.setParams(params)
126+
.setPrincipal(principal)
127+
.setSni(sni)
128+
.build();
129+
130+
return AuthValidator.validate(unifiedHttpRequest, trustManager.getRules());
131+
}
132+
133+
private Map<String, List<String>> getHeaders(HttpServletRequest request) {
134+
Map<String, List<String>> headers = new HashMap<>();
135+
Enumeration<String> headerNames = request.getHeaderNames();
136+
while (headerNames.hasMoreElements()) {
137+
String key = headerNames.nextElement();
138+
Enumeration<String> headerValues = request.getHeaders(key);
139+
List<String> values = new ArrayList<>();
140+
while (headerValues.hasMoreElements()) {
141+
values.add(headerValues.nextElement());
142+
}
143+
headers.put(key, values);
144+
145+
}
146+
return headers;
147+
}
148+
149+
private Map<String, List<String>> getParams(HttpServletRequest request) {
150+
Map<String, List<String>> params = new HashMap<>();
151+
Enumeration<String> paramNames = request.getParameterNames();
152+
while (paramNames.hasMoreElements()) {
153+
String key = paramNames.nextElement();
154+
List<String> values = Arrays.asList(request.getParameterValues(key));
155+
params.put(key, values);
156+
}
157+
return params;
158+
}
159+
160+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 1999-2020 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.util;
17+
18+
import java.util.Collection;
19+
import java.util.Map;
20+
21+
/**
22+
* @author Eric Zhao
23+
* @author lwj
24+
* @since 2.0.0
25+
*/
26+
public final class CollectionUtil {
27+
28+
private CollectionUtil() {}
29+
30+
public static boolean isEmpty(Collection<?> c) {
31+
return c == null || c.isEmpty();
32+
}
33+
34+
public static boolean isEmpty(Map<?, ?> c) {
35+
return c == null || c.isEmpty();
36+
}
37+
}

0 commit comments

Comments
 (0)