微服务实战之安全性

115 阅读5分钟

微服务和其他服务一样, 安全性是不可或缺的重要属性, 任务人来访问服务必需满足以下三个基本要求

安全要求

  • Authentication 认证 用户必需是通过认证的合法用户

  • Authorization 授权 用户必需是经过授权的合法用户, 所访问的模块是在其权限范围之内的

  • Audit 可审查和追溯 用户的访问和操作是可以审查和追溯的

还有一点, 用户的个人敏感信息 PII (Personal Insentive Information ) 是不可在服务器随意存放的, 密码必须经过不可逆的哈希之后再存储在数据库中, 个人的邮件, 电话等信息均不可存放在日志文件中, 只可以放在有访问限制的数据管理系统中

传输安全

传输层的基本协议是 TCP 和 UDP, 对应的安全协议是 TLS 和 DTLS, 在媒体传输中也有 SRTP, 它们的原理类似, 先用 RSA 之类的不对称加密协商一个随机密钥, 然后用这个密钥使用对称加密方式来加密所传输的内容

TLS 最新版本是 TLS v1.3 , 现在流行的版本是 TLS v1.2

  • RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
  • RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2
  • RFC6347: Datagram Transport Layer Security Version 1.2

TLS的主要目标是在两个通信对端提供一个加密通道:

  1. 认证的: 通道的服务器端总是需要认证的, 而客户端的认证是可选的
  2. 保密的: 通道上跑的数据只是在通信端点之间可见,第三方顶多可以看到长度而无法获知加密过的内容
  3. 完整的: 通道上的传输的数据是完整的, 任何对数据的篡改都会被检测出来

TLS 协议主要包括两部分:

  1. 握手协议:认证参与通信的双方, 协商加密方式和参数, 并创建共享的密钥
  2. 记录协议: 使用握手协议协商的参数来保护通信双方所传输的数据

应用层的诸多协议 HTTP, SMTP, IMAP, POP, SIP, 及 XMPP 都可以由下层的 TLS/DTLS 来保护数据的安全. 在实践中, 推荐使用OWASP(Open Web Application Security Project) 有一个检查表可供参考

www.owasp.org/index.php/T…

TLS 握手过程如下

TLS 握手

TLS 记录最大为16KB, 每条记录包含5个字节的首部, 最多32字节的MAC

TLS 记录

walter@WalterPC:~$ curl -vvv -I https://tools.ietf.org/html/rfc8446
*   Trying 4.31.198.61...
* TCP_NODELAY set
* Connected to tools.ietf.org (4.31.198.61) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /home/walter/anaconda3/ssl/cacert.pem
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: OU=Domain Control Validated; CN=*.tools.ietf.org
*  start date: Oct  1 11:34:00 2017 GMT
*  expire date: Nov 30 23:34:19 2018 GMT
*  subjectAltName: host "tools.ietf.org" matched cert's "tools.ietf.org"
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=Starfield Technologies, Inc.; OU=http://certs.starfieldtech.com/repository/; CN=Starfield Secure Certificate Authority - G2
*  SSL certificate verify ok.
> HEAD /html/rfc8446 HTTP/1.1
> Host: tools.ietf.org
> User-Agent: curl/7.60.0
> Accept: */*
> 
< HTTP/1.1 200 OK
HTTP/1.1 200 OK

SNI - Sever Name Indication 服务器名称指示

应用层的安全

用户名密码登录, session/cookie

当用户验证通过时,生成一个Session id, 存入内存,这样用户之后的登录都会携带这个Session id, 应用程序找到对应的Session 就认为这是一个合法并经过验证的用户,这样当然非常简单,问题在于如果换了个服务器,就找不到这个Session 了,所以通常的做法是用分布式或集中式存储, 详见 微服务之会话管理

下面重点讲讲 OAuth2 协议

举个例子, 我曾经当过秘书, 秘书如果需要调阅机密档案, 一般要经过如下步骤

  1. 秘书找保密室领导申请调阅某机密文档
  2. 领导签字批准
  3. 秘书拿着领导签字去找档案员拿钥匙
  4. 档案员给了一把档案柜密码锁的临时密码 (临时密码是有时效性的, 过期无效)
  5. 秘书拿着临时密码去开文件柜拿文档
  6. 秘书拿到文档查阅所需内容

这个过程就是一个典型的 OAuth2 过程, OAuth 协议定义的四种角色如下

  • Client 是秘书
  • Resource Owner 是领导
  • Authorization Server 是 档案员
  • Resource Server 是档案柜, resource 就是档案

标准流程如下

其中

  • Authorization Grant 是资源所有者(领导)给予的授权, 也就是 Resource Owner 所给予的凭据, OAuth协议中定义了四种方式
  • authorization code 授权码, 就好比领导给的签字
  • implicit 隐含方式
  • resource owner password 领导给你的一个临时密码
  • credentials, and client credentials
  • Access Token 是档案柜密码锁的临时密码
  • Protected Resource 是机密档案

获取访问令牌 access_token

  • 请求
POST /v1/oauth2/token HTTP/1.1

Authorization: Basic xxx
Content-Type: application/x-www-form-urlencoded

grant_type=password
&username=walter
&password=pass
&scope=api
  • 响应

HTTP1.1 200 OK Content-Type: application/json

{ "access_token": "xxxyyy", "token_type": "bearer", "expires_in": "3000000", "refresh_token": "xxxzzz"

}

通过访问令牌来调用 API

GET /api/v1/users/4c65201a-2052-4cab-8b22-4c60148a1178 HTTP/1.1 Authorization: Bearer xxxyyy

响应

HTTP1.1 200 OK Content-Type: application/json

{ "id": "4c65201a-2052-4cab-8b22-4c60148a1178", "name": "walter"

}

access_token 过期之后

HTTP1.1 401 Unauthorized Content-Type: application/json

{ "error": "invalid_token" }

参考资料