前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >保护微服务(第一部分)

保护微服务(第一部分)

作者头像
用户1196457
发布2018-07-04 15:31:04
2.5K0
发布2018-07-04 15:31:04

保护微服务(第一部分)

面向服务的体系结构(SOA)引入了一种设计范式,该技术讨论了高度分离的服务部署,其中服务间通过标准化的消息格式在网络上通信,而不关心服务的实现技术和实现方式。每个服务都有一个明确的,公开的服务描述或服务接口。实际上,消息格式是通过SOAP进行标准化的,SOAP是2000年初由W3C引入的标准,它也基于XML--服务描述通过WSDL标准化,另一个W3C标准和服务发现通过UDDI标准化--另一个W3C标准。所有这些都是基于SOAP的Web服务的基础,进一步说,Web服务成为SOA的代名词 - 并导致其失去作为一种架构模式的本义。SOA的基本原则开始淡化。WS- *栈(WS-Security,WS-Policy,WS-Security Policy,WS-Trust,WS-Federation,WS-Secure Conversation,WS-Reliable Messaging,WS-Atomic Transactions,WS-BPEL等)通过OASIS,进一步使SOA足够复杂,以至于普通开发人员会发现很难消化。

现在,经过这么多年,我们又开始了一段过去实现SOA的基本原理-我们将其称为微服务的旅程。微服务将为应用程序设计提供专注,范围和模块化的方法。

微服务和物联网(IoT)、容器化以及区块链一样,是现在最流行的术语之一。每个人都在谈论微服务,每个人都希望实现微服务。“微服务”一词首次提出是在2011年5月威尼斯的软件架构师研讨会上,它被用来解释他们已经见证了一段时间的常见架构风格。

Sam Newman所著的《构建微服务》是一本非常棒的书,当你阅读它时,你会意识到,微服务不仅仅是SOA,这不仅仅是一个架构模式 - 而是围绕一个架构模式的新文化建设,由主要目标驱动 - 更快的部署或生产速度。

构建微服务〜设计细粒系统

在保护微服务方面有多种观点:

  • 安全开发生命周期和测试自动化:微服务背后的关键推动力是生产速度。人们应该能够对服务进行更改,对其进行测试并立即将其部署到生产环境中。为了确保我们不在代码级引入安全漏洞,我们需要有一个适当的静态代码分析和动态测试计划 - 最重要的是这些测试应该是持续交付(CD)过程的一部分。应该在开发生命周期的早期识别出任何漏洞,并缩短反馈周期。
  • DevOps安全性:有多种微服务部署模式 - 但最常用的是每服务器模式。该主机并不一定意味着一台物理机器-也有可能这将是一个容器(Docker),这时我们需要考虑容器级级别的安全。我们如何将一个容器与其他容器隔离开来,以及容器与主机操作系统之间有什么隔离级别?
  • 应用程序级安全性:我们如何验证和访问控制用户以使用微服务,以及如何保护微服务之间的沟通渠道?

这篇博文介绍了一种安全模型,以解决我们在应用程序级别保护微服务所面临的挑战。

单体系统与微服务

在单体应用程序中,所有服务都部署在同一个应用程序服务器中,应用程序服务器本身提供会话管理功能。服务之间的交互是本地调用,所有服务都可以共享用户的登录状态,每个服务(或组件)都不需要对用户进行身份验证。身份验证将在拦截所有服务调用的拦截器中集中完成。身份验证完成后,如何在服务(或组件)之间传递用户的登录上下文因平台而异。下图显示了单体应用程序中多个组件之间的交互。

在Java EE环境中,拦截器可以是一个servlet过滤器。这个servlet过滤器将拦截所有到达它注册的上下文的请求,并执行认证。服务调用者应该携带有效的凭据或可以映射到用户的会话令牌,一旦servlet过滤器找到用户,它就可以创建一个登录上下文并将其传递给下游组件,每个下游组件都可以从登录上下文中识别用户以进行任何授权。

安全性在微服务环境中变得具有挑战性。在微服务领域,这些服务的作用域和部署是在分布式的多个容器中。服务交互不再是本地的,而是远程的,大多数是通过HTTP交互。下图显示了多个微服务之间的交互。

这里面临的挑战是,我们如何以对称的方式验证用户并在微服务之间传递登录上下文,以及每个微服务如何授权用户。

保护服务间的通信

在这篇博文中,我将讨论两种保护服务到服务通信的方法。一个基于JWT,另一个基于TLS相互认证。

JSON Web令牌(JWT)

JWT(JSON Web令牌)定义了一个在相关方之间传输数据的容器。它可以用来:

  • 在相关方之间传播一个人的身份。
  • 在相关方之间传播用户权利。
  • 通过不安全的渠道在相关方之间安全地传输数据。
  • 断言一个人的身份,鉴于JWT的接受者信任断言方。

已签名的JWT称为JWS(JSON Web签名),加密的JWT称为JWE(JSON Web加密)。事实上,JWT本身并不存在 - 要么是JWS要么是JWE。它就像一个抽象类--JWS和JWE是具体的实现。

JWT,JWS和JWE不是傻瓜!

从一个微服务到另一个微服务的用户上下文可以与JWS一起传递。由于JWS通过上游微服务已知的密钥签名,因此JWS将携带最终用户身份(如JWT中的声明)和上游微服务的身份(通过签名)。为了接受JWS,下游的微服务首先需要根据JWS本身中嵌入的公钥验证JWS的签名。这还不够 - 我们还需要检查我们是否信任该密钥。微服务之间的信任可以通过多种方式建立,一种方法是将可信证书通过服务提供给每个微服务。毫无疑问,这种方式在微服务部署中难以扩展。我想建议的方法是建立一个私人证书颁发机构(CA),如果需要的话,还可以由不同的微服务团队建立中级证书颁发机构。现在,下游微服务不再信任每个单独的证书,而是信任根证书颁发机构或中介,这将大大减少证书配置的开销。

JWT验证的成本

每个微服务必须承担JWT验证的成本,其中还包括验证令牌签名的加密操作。在微服务级别缓存JWT可以降低重复令牌验证带来的开销。缓存过期时间必须与JWT到期时间相匹配。如果JWT到期时间非常短,缓存的作用将会降低。

识别用户

JWT 在其声明集中携带名为sub的参数,该参数代表拥有JWT的主体或用户。除了主体标识符之外,JWT还可以携带用户属性,例如first_namelast_nameemail等。微服务可以通过查找这些属性在操作过程中识别用户。属性的值仅对给定颁发者是唯一的。如果你有一个微服务,它接受来自多个发行人的令牌,那么发行者和属性的组合将决定用户的唯一性。

JWT声明集中的aud参数指定令牌的目标受众。它可以是单个收件人或一组收件人。在进行任何验证检查之前,令牌收件人必须首先检查JWT是否发布给他使用,如果不是,应立即拒绝。在发布令牌之前,令牌发行者应该知道令牌的预期接收者(或接收者),并且aud参数的值必须是令牌发行者与接收者之间的预先约定的值。在微服务环境中,可以使用正则表达式来验证令牌的受众,例如,令牌中aud的值可以是* .facilelogin.com,facilelogin.com域下的每个接受者都可以拥有自己的aud值:foo.facilelogin.combar.facilelogin.com

TLS相互认证

无论是在TLS相互认证还是基于JWT的方法中,每个微服务都需要拥有自己的证书。这两种方法之间的区别在于,在基于JWT的认证中,JWS可以同时承载最终用户身份和上游服务身份,而在使用TLS相互身份验证时,最终用户身份必须在应用程序级别传递。

证书撤销

在我们上面讨论的两种方法中,证书撤销都有点棘手。证书撤销是一个难以解决的问题—尽管有多种选择:

  • CRL(认证撤销清单/ RFC 2459)
  • OCSP(在线证书状态协议/ RFC 2560)
  • OCSP Stapling (RFC 6066)
  • 必须OCSP Stapling(draft-hallambaker-muststaple-00)

CRL是一种不常用的技术。启动TLS握手的客户端必须从对应的证书颁发机构(CA)获取撤销证书的长列表,然后检查服务器证书是否在撤销的证书列表中。客户端可以在本地缓存CRL,而不是为每个请求做这件事,但是这会遇到了基于陈旧数据做出安全决策的问题。当使用TLS相互认证时,服务器也必须对客户端执行相同的证书验证。最终,人们认识到CRL不能工作,并开始构建新的OCSP。

在OCSP的世界里,事情比CRL好一点。TLS客户端可以检查特定证书的状态,而无需从证书颁发机构下载完整的撤销证书列表,换言之,每次客户端与新的下游微服务对话时,它都必须与相应的OCSP响应者通信以验证服务器(或服务)证书的状态 - 并且服务器必须对客户端证书执行相同的操作。这导致OCSP响应者身上产生了很大的流量。虽然客户依然可以缓存OCSP的决策,但这又会导致相同的陈旧数据问题。

使用OCSP Stapling,客户端不需要每次与下游微服务进行交互时都转到OCSP响应者。下游微服务将从相应的OCSP响应者处获得OCSP响应,并将响应附加到证书本身。由于OCSP响应由相应的证书颁发机构签署,客户端可以通过验证签名来接受它。这使事情变得更好,现在服务和OCSP响应者交互,而不是客户端。但在TLS相互认证模式中,与普通的OCSP相比,这并不会带来任何额外的好处。

使用OCSP must stapling,服务(下游微服务)为客户端(上游微服务)提供了一个保证,将OCSP响应附加到它在TLS握手期间接收到的服务证书。如果OCSP响应未附加到证书,则客户端必须立即拒绝该连接。

短生命周期证书

从最终用户的角度来看,短期证书的行为与普通证书的工作方式相同,区别是短期证书的到期时间很短,TLS客户端不需要对短期证书进行CRL或OCSP验证,而是检查证书本身签署的到期时间。

Netflix和短生命周期证书

短期证书面临的挑战主要在于其部署和维护,自动化是解决之道!Netflix建议使用分层方法构建短期证书部署,您将拥有驻留在TPM(可信平台模块)或SGX(软件防护扩展)上的系统标识或长期凭据,并且SGX具有很多安全性,然后使用该凭据获取短期证书,然后为您的微服务提供短期证书,该证书将被另一个微服务使用。每个微服务都可以使用其长期凭据定期刷新短期证书。拥有短期证书并不够 - 托管服务(或TLS终结器)的底层平台应该支持动态更新服务器证书。许多 TLS 终端都支持动态重载服务器证书,但大多数情况下不能保证零停机。

边缘安全

将一组微型服务展示给世界其他地方的常见模式是通过API网关模式。使用API​​网关模式 - 需要暴露在外的微服务将在API网关中具有相应的API。并非所有的微服务都需要从API网关中暴露出来。

最终用户对微服务的访问(通过API)应在边缘或API网关处进行验证,保证API的最常见模式是OAuth 2.0。

OAuth 2.0

OAuth 2.0是访问委派的框架,它允许某人代表别人做某件事。OAuth 2.0引入了多种授权类型。OAuth 2.0中的授权类型解释协议,对象(客户端)应该只能访问资源所有者同意代表他/她访问的资源。此外,还有一些授权类型,它们只是代表自己(client_credentials)解释获取令牌的协议 - 换句话说,客户端也是资源所有者。下图解释了高层视觉下的OAuth 2.0协议,它描述了OAuth客户端,资源所有者,授权服务器和资源服务器之间的交互。

任何对象想要通过API网关访问微服务,必须先获得有效的OAuth令牌。系统以自身身份或者他人代表的身份访问微服务。对于后一种情况,例如,用户登录到Web应用程序,现在Web应用程序将代表登录的用户访问微服务。

让我们看看端到端的通信是如何工作的,如上图所示:

  • 用户通过身份提供者登录到网络应用程序/移动应用程序,网络应用程序/移动应用程序通过OpenID Connect(也可以是SAML 2.0)进行认证。
  • 网络应用获取OAuth 2.0 access_token和id_token。id_token将识别Web应用程序的最终用户。如果使用SAML 2.0,那么Web应用程序需要与其信任的OAuth授权服务器的令牌端点进行通话,并根据OAuth 2.0的SAML 2.0授权类型将SAML令牌交换到OAuth access_token。
  • Web应用程序调用一半的最终用户的API - 将access_token传递给API请求。
  • API网关拦截来自Web应用程序的请求,提取出access_token,与Token Exchange端点(或STS)通信,这将验证access_token,然后向API网关发出JWT(由其签名)。这个JWT也将携带用户上下文。当STS验证access_token时,它将通过introspection API 与相应的OAuth授权服务器通信。
  • API网关将通过JWT以及对下游微服务的请求。
  • 每个微服务将验证它接收的JWT,然后对于下游服务调用,它可以创建一个由它自己签名的新JWT,并将其与请求一起发送。另一种方法是使用嵌套的JWT - 新的JWT也将携带以前的JWT。

采用这种方法,只有来自外部客户端的API调用才会通过API网关。当一个微服务与另一个微服务对话时则不需要通过网关。此外,从给定的微服务角度来看,无论您是从外部客户端还是其他微服务获取请求,您获得的都是JWT - 因此这是一个对称安全模型。

访问控制

授权是一项业务功能,每个微服务都可以决定其操作授权的标准。在最简单的授权形式中,我们检查给定用户是否可以对特定资源执行给定操作。动作和资源的组合被称为许可。授权检查评估给定用户是否具有访问给定资源所需的最小权限集合。资源可以定义谁可以执行,对其执行哪些操作。给定资源所需权限的声明可以通过多种方式完成。

XACML(可扩展访问控制标记语言)

XACML是细粒度访问控制的事实标准。它引入了一种方法来以基于XML的领域特定语言(DSL)中的细粒度方式来表示访问资源所需的一组权限。

上图显示了XACML组件的体系结构。策略管理员首先需要通过PAP(策略管理点)定义XACML策略,这些策略将存储在策略存储中。为了检查给定实体是否有权访问给定资源,PEP(策略执行点)必须拦截访问请求,创建一个XACML请求并将其发送到XACML PDP(策略决策点)。XACML请求可以携带任何有助于PDP决策过程的属性,例如,它可以包括主题标识符,资源标识符和给定主体将在资源上执行的动作。需要授权用户的微服务必须通过从JWT中提取相关属性并与PDP通信来构建XACML请求。PIP(策略信息点)在PDP发现在XACML请求中缺少策略评估所需的某些属性时出现,然后,PDP将与PIP进行交互以找到相应的缺失属性。PIP可以连接到相关数据存储查找属性,然后将这些属性提供给PDP。

嵌入式PDP

远程PDP模型存在一些缺陷,可能很容易违反基本的微服务原则:

  • 性能成本:每次需要进行访问控制检查时,相应的微服务必须通过网络与PDP进行通信。通过在客户端进行决策缓存,可以减少运输成本和政策评估成本,但通过缓存,我们就会基于陈旧数据做出安全决策。
  • 策略信息点(PIP)的所有权:每个微服务都应拥有其PIP的所有权,这些PIP知道从哪里引入进行访问控制所需的数据。通过上述方法,我们正在构建一个“单片”PDP,其中包含所有PIPs - 与所有微服务相对应。

如上图所示,嵌入式PDP将遵循事件模型,其中每个微服务将订阅其感兴趣的主题以从PAP获取适当的访问控制策略 - 然后更新嵌入式PDP。微服务团队可以拥有PAP,或者可以是全球多租户模式的PAP。当新策略可用或有策略更新时,PAP将向相应主题发布事件。

这种方法也不会违反微服务中的'不可变服务器 '概念。不可变的服务器的含义是 - 在持续交付流程结束时,直接从服务器加载的配置中构建服务器或容器,并且应该能够使用相同的配置一次又一次构建相同的容器。所以,我们不希望任何人登录到服务器并在那里做任何配置更改。使用嵌入式PDP模型,尽管服务器在运行时加载了相应的策略,但如果我们启动一个新的容器,它也会获得相同的策略集。

在本文结束之前,还有一个重要的问题需要回答,API网关在授权环境下的作用是什么,我们可以拥有全球可访问的访问控制策略 - 适用于最终用户,在网关上实施 - 而不是服务级策略,服务级策略必须在服务级别执行。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 保护微服务(第一部分)
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档