身份认证和授权
1.单点登录(SSO)
当主体试图访问一个资源,他会被定向到一个身份提供者那里进行身份验证,身份提供者验明正向后会发消息给服务提供者,让服务提供者来决定是否允许它访问资源。
SAML和OpenID Connect/OAuth2.0是企业领域中占据统治地位的单点解决方案。
2.单点登录网关
现在问题来了,多个微服务是不是也要单独地与单点登录系统交互,显然这样是不合理的,这意味着大量的重复工作。我们可以使用单点登录网关来帮助我们完成这一工作,在使用者通过单点登录网关后,可以将用户名和角色等用户信息放入HTTP头信息,传递给下游服务。
同时,网关应该提供的是粗粒度的身份验证,而不应该过于具体,如我们可以使用它来完成对是否登录、取角色、是否访问某个服务这类的验证,而不应该具体到“是拥有view.html页面50条还是100条数据的导出权限”。
网络传输和服务间传输的身份验证和授权
从浏览器中输入用户和密码,到真正的服务提供者,这中间是一个漫长的过程,通过HTTP有很高的风险,因为用户和密码并没有以安全的方式发送,任何中间方都可以看到HTTP头的信息并读取里面的数据,因此HTTP基本身份验证通常应该使用HTTPS进行通信。
使用HTTPS时,浏览器到服务器的通信将获得强有力的保证,但是服务器端要管理的SSL证书,这有一个额外的行政和运营负担,同时SSL上的流量不能被反向代码服务器(如Varnish或Squid)所缓存,这意味着,如果你需要缓存信息,就不得不在服务端或浏览器内部实现,你可以在负载均衡中把HTTPS的请求转成HTTP请求,然后在负载均衡之后就可以使用缓存了。
如果你已经在使用SAML或OpenID Connect作为身份验证和授权方案,你可以在服务之间的交互中也使用它们。你可以针对服务也创建一些凭证,如果凭证被泄露,只需要撤销有限的受影响的凭证即可。(这里我感觉像配置Git的SSH PublicKey和PrivateKey一样。)
同时我们也可以使用TLS(Transport Layer Security安全传输协议),在这里,每个客户端都安装了一个X.509证书,用于客户端和服务器端之间建立通信链路,服务器端可以验证客户端证书的真实性。当你特别关注所发数据的敏感性,或无法控制发送数据所使用的网络时,才考虑使用这种技术。
另一种方式,我们还可以使用HTTP之上的HMAC(Hash-based Message Authentication Code基于哈希的消息码)对请求进行签名,它是OAuth规范的一部分。使用HMAC,请求主体和私有密钥一起被哈希处理,生成的哈希值随请求一起发送,服务器使用请求主体和自己的私钥副本重建哈希值,如果匹配则接受请求。这样做的好处是,如果一个中间人更改了请求,那么哈希值会不匹配,服务器便知道该请求被篡改过,且私钥永远不会随请求发送,因此不会存在传输过程中泄露的问题,而且通信更容易被缓存,生成哈希的开销要低于处理HTTPS的开销。
HMAC也存在缺点,首先客户端和服务器端需要一个共享的、以某种方式交流的密钥,其次这是一个模式而不是标准,可以参看AWS的S3 API,最后请求中所带的其他数据,对网络嗅探来说仍然是可见的。
另外,在大部分的组织内部,服务间的通信被认为是安全的,而没有采取任何防备。我们也可以采用上面的方式对组织内部的通信进行安全加固。
提供出的公共API安全:API密钥
API密钥允许服务识别出是谁进行调用,然后对他们能做的进行限制,限制通常不仅限于对特定资源的访问,还可以扩展到类似于针对特定的调用者限速,以保护其他人服务调用的质量。
通常情况下,我们会在系统中集中管理API密钥,API网关(API Gateway)模型在这个领域很受欢迎。
一个问题:代理人欺骗
当我登录了系统后,我再通过尝试,看是否能够获得其他客户或者订单的信息,它们原来不属于我,但由于接口只是提供order/12345之类的规则,并没有验证信息,万一这样成功了呢?那么我就可以作为一个假的代理人去欺骗系统的数据。
解决这个问题的方法是在应用程序中加入验证,使这个人只能查询自己的订单,也可以在请求中加入原始的凭证。
静态数据的安全
有些组织中,服务器中的静态数据是完全没有加密的,这有可能会生成安全漏洞。有一些产品已经提供了加密算法,比如SqlServer和Oracle就提供了可以加密表的某一列值的功能,同时我们可以采用已知的加密算法(不要自己去尝试写一套加密算法)对静态数据进行加密,同时对备份也进行加密。
全面防御
我们应该从浏览器到应用程序服务器再到数据库都存在安全防御措施,防火墙(设置允许的入口和出口)、日志(不要将敏感的数据写到日志中)、入侵检测系统(IDS,可以监控网络或主机,当发现可疑行为时报告问题)、入侵预防系统(IPS,监控可疑行为并阻止它的发生)、网络隔离(我们可以把服务放进不同的网段)、操作系统(自动定时打补丁、设置OS的安全策略等)。
举个例子
先看一下不安全的架构
在这里,所有的请求都使用普通的HTTP传输,但我们希望在传输的过程中数据不要被篡改;同时我们要限制公共API的使用范围和使用频率;另外我们希望第三方系统与我们的交互是受保护的,而避免被竞争对手所获取;我们希望客户服务中的数据是完全加密的,这样即使发生拖库的情况,黑客也不能获取相应的数据。
基于这些设定,我们提供了一种安全的架构,如下所示:
一些可供借鉴的法则和实践
OWASP十大列表和SP安全测试框架
微软安全开发生命周期(http://www.microsoft.com/en-us/sdl/default.aspx)
参考
《微服务设计》(Sam Newman 著 / 崔力强 张骏 译)