架构09-可靠通信
1、零信任网络
(1)微服务与分散治理
- **定义:**微服务不追求统一的技术平台,而是提倡让团队有自由选择的权利,不受制于语言和技术框架。
- **优点:**在开发阶段,分散治理打破了由技术栈带来的约束,带来了更大的灵活性。
- **挑战:**在运维阶段,尤其是考虑安全问题时,多种语言和框架(如 Java、Golang、Python、Node.js)共同组成的微服务系统,出现安全漏洞的概率更高。
(2)传统的基于边界的安全模型
- **定义:**根据宿主机的特征(如位置、IP 地址、子网等)将网络划分为不同区域,不同区域对应不同的风险级别和访问权限,安全防护措施集中在区域边界上。
- 优点:
- 减少安全设施对应用系统复杂度的影响。
- 降低网络传输性能的额外损耗。
- 局限性:
- 无法防止内网中某台服务器被攻陷后,攻击者以该服务器为跳板侵入整个内网。
- 固有缺陷:边界安全措施无法防止内网中的"猪队友"。
(3)零信任安全模型
- **定义:**不以某种固有特征自动信任任何流量,除非明确得到了能代表请求来源的身份凭证。
- **中心思想:**假设服务总是会出错,承认一定会有被攻陷的服务。
- 具体落地原则:
- **身份只来源于服务:**服务间通信的身份凭证必须明确,不再依赖 IP 地址、主机名等。
- **服务之间没有固有的信任关系:**每个服务节点都需要进行身份验证和授权。
- **集中、共享的安全策略实施点:**安全需求下沉至云原生基础设施,实现集中管理和自动化。
- **受信的机器运行来源已知的代码:**确保代码和配置经过认证,运行在认证过的环境中。
- **自动化、标准化的变更管理:**通过基础设施实现安全功能,确保变更的自动化和标准化。
- **强隔离性的工作负载:**使用轻量级虚拟化方案(如 gVisor、Kata Containers)提高隔离性。
(4)Google 的零信任安全实践
- **Google Front End:**边缘代理,保护内部服务免受 DDoS 攻击。
- **Application Layer Transport Security (ALTS):**服务认证机制,实现双向认证和传输加密。
- **Service Access Policy:**管理服务间的认证、鉴权和审计策略。
- **Binary Authorization:**部署时检查机制,确保软件供应链各阶段符合安全检查策略。
- **Host Integrity:**机器安全启动程序,验证 BIOS、BMC、Bootloader 和操作系统内核的数字签名。
- **gVisor:**轻量级虚拟化方案,提高容器的隔离性。
2、服务安全
(1)建立信任
- 零信任网络的基本概念
- **核心原则:**零信任网络中不存在默认的信任关系。
- **信任建立:**所有服务调用和资源访问的成功与否,都需以调用者与提供者间已建立的信任关系为前提。
- 信任建立方式
- 真实世界:
- 基于共同私密信息的信任:例如共享密码或生物识别信息。
- 基于权威公证人的信任:例如证书颁发机构(CA)。
- 网络世界:
- 基于权威公证人的信任:公开密钥基础设施(PKI)。
- PKI 的作用:构建传输安全层(TLS)的必要基础。
- 传输安全层(TLS)
- 目的:防止中间人攻击,确保通信过程的安全。
- 传输路径风险:DNS 服务器、代理服务器、负载均衡器和路由器等节点可能监听或篡改传输信息。
- 解决方案:启用 TLS 对传输通道进行加密,确保只有接收者可以解密发送者发出的内容。
- TLS 的实现
- 基本步骤:
- 预置 CA 根证书:在部署服务器时预置好 CA 根证书。
- 签发 TLS 证书:用该 CA 为部署的服务签发 TLS 证书。
- 实际操作挑战:
- 运维压力:面对大量且动态扩缩的服务节点,手动部署和轮换根证书难以持续。
- 自动化需求:必须集中在基础设施中自动进行的安全策略实施点。
- 单向 TLS 认证 vs 双向 TLS 认证
- 单向 TLS 认证:
- 特点:只需服务端提供证书,客户端验证服务端身份。
- 适用场景:公开的服务,任何客户端均可访问。
- 保护重点:防止客户端连接到冒牌服务器。
- 双向 TLS 认证(mTLS):
- 特点:客户端和服务端均需提供证书,互相验证对方身份。
- 适用场景:私密的服务,仅特定身份的客户端可访问。
- 保护重点:防止客户端连接到冒牌服务器,同时防止服务端被非法用户越权访问。
(2)认证
- **认证概述:**在微服务架构中,认证是指验证服务调用者身份的过程,确保只有合法的调用者才能访问服务。认证可以分为两类:服务认证和请求认证。
- **服务认证 **
- Istio 版本的 Fenix's Bookstore
- 双向 TLS 认证(mTLS):
- 实现机制:Istio 提供了基础设施支持,可以在不修改代码的情况下启用 mTLS。
- 配置示例:
yaml
复制代码
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: authentication-mtls
namespace: bookstore-servicemesh
spec:
mtls:
mode: STRICT
+ 宽容模式(Permissive Mode):允许同时接受纯文本和 mTLS 流量,方便逐步迁移。
yaml
复制代码
mode: PERMISSIVE
- **Spring Cloud 版本的 Fenix's Bookstore**
* OAuth 2.0 客户端模式:
+ 实现机制:每个客户端与认证服务器约定密钥,通过 JWT 令牌进行身份验证。
+ 代码示例:
java
复制代码
private static final List clients = Arrays.asList(
new Client("bookstore_frontend", "bookstore_secret", new String[]{GrantType.PASSWORD, GrantType.REFRESH_TOKEN}, new String[]{Scope.BROWSER}),
new Client("account", "account_secret", new String[]{GrantType.CLIENT_CREDENTIALS}, new String[]{Scope.SERVICE}),
new Client("warehouse", "warehouse_secret", new String[]{GrantType.CLIENT_CREDENTIALS}, new String[]{Scope.SERVICE}),
new Client("payment", "payment_secret", new String[]{GrantType.CLIENT_CREDENTIALS}, new String[]{Scope.SERVICE}),
new Client("security", "security_secret", new String[]{GrantType.CLIENT_CREDENTIALS}, new String[]{Scope.SERVICE})
);
+ 资源服务器配置:
java
复制代码
public ClientCredentialsResourceDetails clientCredentialsResourceDetails() {
return new ClientCredentialsResourceDetails();
}
+ JWT 令牌验证:
java
复制代码
@Named
public class RSA256PublicJWTAccessToken extends JWTAccessToken {
RSA256PublicJWTAccessToken(UserDetailsService userDetailsService) throws IOException {
super(userDetailsService);
Resource resource = new ClassPathResource("public.cert");
String publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
setVerifierKey(publicKey);
}
}
- 请求认证
- Istio 版本的 Fenix's Bookstore
- JWT 令牌验证:
- 实现机制:Istio 自动验证 JWT 令牌,提取用户身份。
- 配置示例:
yaml
复制代码
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: authentication-jwt-token
namespace: bookstore-servicemesh
spec:
jwtRules:
- issuer: "icyfenix@gmail.com"
fromHeaders:
- name: Authorization
prefix: "bearer "
jwks: |
{
"keys": [
{
"e": "AQAB",
"kid": "bookstore-jwt-kid",
"kty": "RSA",
"n": "i-htQPOTvNMccJjOkCAzd3YlqBElURzkaeRLDoJYskyU59JdGO-p_q4JEH0DZOM2BbonGI4lIHFkiZLO4IBBZ5j2P7U6QYURt6-AyjS6RGw9v_wFdIRlyBI9D3EO7u8rCA4RktBLPavfEc5BwYX2Vb9wX6N63tV48cP1CoGU0GtIq9HTqbEQs5KVmme5n4XOuzxQ6B2AGaPBJgdq_K0ZWDkXiqPz6921X3oiNYPCQ22bvFxb4yFX8ZfbxeYc-1rN7PaUsK009qOx-qRenHpWgPVfagMbNYkm0TOHNOWXqukxE-soCDI_Nc--1khWCmQ9E2B82ap7IXsVBAnBIaV9WQ"
}
]
}
forwardOriginalToken: true
- **Spring Cloud 版本的 Fenix's Bookstore**
* JWT 令牌验证:
+ 实现机制:Spring Security 自动验证 JWT 令牌,提取用户身份。
+ 代码示例:
java
复制代码
@Named
public class RSA256PublicJWTAccessToken extends JWTAccessToken {
RSA256PublicJWTAccessToken(UserDetailsService userDetailsService) throws IOException {
super(userDetailsService);
Resource resource = new ClassPathResource("public.cert");
String publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
setVerifierKey(publicKey);
}
}
(3)授权
- **授权的基本概念:**授权是在认证之后的一个步骤,确保合法的调用者能够访问其被允许的资源。在微服务架构中,授权通常基于角色(Role-Based Access Control, RBAC)进行控制,无论调用者是机器(服务)还是人类(最终用户)。
- Istio 版本的授权实现
- Istio 提供了一种在基础设施层面上实现授权的方法,通过
AuthorizationPolicy
CRD(Custom Resource Definition)来配置授权规则。
- 示例配置
yaml
复制代码
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authorization-peer
namespace: bookstore-servicemesh
spec:
action: ALLOW
rules:
- from:
- source:
namespaces: ["bookstore-servicemesh"]
to:
- operation:
paths:
- /restful/accounts/*
- /restful/products*
- /restful/pay/*
- /restful/settlements*
methods: ["GET", "POST", "PUT", "PATCH"]
- from:
- source:
namespaces: ["istio-system"]
- 外部请求的控制
yaml
复制代码
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authorization-request
namespace: bookstore-servicemesh
spec:
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
notNamespaces: ["bookstore-servicemesh"]
to:
- operation:
paths:
- /restful/accounts/*
- /restful/pay/*
- /restful/settlements*
- **优点**
* **便捷性:**通过配置文件实现,无需修改应用代码。
* **安全性:**集中管理,减少代码中的安全漏洞。
* **无侵入:**对现有应用的影响最小。
* **统一管理:**可以在一个地方集中管理所有服务的授权规则。
- Spring Cloud 版本的授权实现
- Spring Cloud 版本的授权控制是通过应用程序代码来实现的,主要使用 Spring Security 提供的工具。
- 第一种方法:ExpressionUrlAuthorizationConfigurer
java
复制代码
http.authorizeRequests()
.antMatchers("/restful/accounts/").hasScope(Scope.BROWSER)
.antMatchers("/restful/pay/").hasScope(Scope.SERVICE);
- 第二种方法:全局方法级安全
java
复制代码
@GET
@Path("/{username}")
@Cacheable(key = "#username")
@PreAuthorize("#oauth2.hasAnyScope('SERVICE', 'BROWSER')")
public Account getUser(@PathParam("username") String username) {
return service.findAccountByUsername(username);
}
@POST
@CacheEvict(key = "#user.username")
@PreAuthorize("#oauth2.hasAnyScope('BROWSER')")
public Response createUser(@Valid @UniqueAccount Account user) {
return CommonResponse.op(() -> service.createAccount(user));
}
- **优点 **
* **灵活性:**可以对每个方法进行细粒度的控制。
* **功能强大:**支持 SpEL 表达式,可以实现复杂的授权逻辑。
- **缺点**
* **侵入性:**需要在代码中添加注解,增加了代码的复杂性。
* **维护成本:**随着服务数量的增加,维护授权规则的成本会增加。