程序锅

  • 首页
  • 分类
  • 标签
  • 归档
  • 关于

  • 搜索
基础知识 Etcd LeetCode 计算机体系结构 Kubernetes Containerd Docker 容器 云原生 Serverless 项目开发维护 ELF 深入理解程序 Tmux Vim Linux Kernel Linux numpy matplotlib 机器学习 MQTT 网络基础 Thrift RPC OS 操作系统 Clang 研途 数据结构和算法 Java 编程语言 Golang Python 个人网站搭建 Nginx 计算机通用技术 Git

Etcd 认证&&鉴权原理

发表于 2022-10-16 | 分类于 Etcd | 0 | 阅读次数 3347

整体架构

鉴权体系架构由控制面和数据面组成。

控制面是指对认证、授权规则进行调整,整体流程如下,

  • 客户端通过鉴权 API 发出调整认证、授权规则的请求。
  • AuthServer 收到请求后,为确保各节点间鉴权元数据一致性,会先通过 Raft 模块进行数据同步。
  • 当对应的 Raft 日志条目被集群半数以上节点确认后,Apply 模块通过鉴权存储 (AuthStore) 模块,执行日志条目的内容,将规则存储到 boltdb 的一系列“鉴权表”里面。

数据面是指在读写 key-value 数据的过程中,判断该读写请求是否合法,整体流程如下,

  • etcd server 收到 put hello 的请求后,会从请求的上下文中获取用户身份信息。
  • 之后先进行身份认证。目前 etcd 实现了两种认证机制,分别是密码认证和证书认证。
    • 如果认证通过,则继续下一步。如果使用了密码认证,这一步则还会给客户端分配一个 Token,在请求返回的时候会把这个 Token 返回给客户端。之后客户端的请求携带此 Token,etcd server 就可以快速完成客户端的身份校验工作。目前 Token 支持 SimpleToken 和 JWT 两种。
    • 如果认证不通过,则拒绝请求。
  • 认证通过之后,再检查对应角色是否有执行 put 操作的权限。针对授权这块,etcd 采用的是 RBAC。
    • 如果权限检查通过,则继续下一步。
    • 如果权限检查不通过,则拒绝请求。
  • 授权检查也通过了的话,则会按照 Put 数据的流程先通过 Raft 共识,然后将数据写入,最后返回请求的响应。

认证

认证的目的是获取 client 的身份,并检查该身份是否合法,防止匿名或不合法用户访问等。目前 etcd 实现了两种认证机制,分别是密码认证和证书认证。

密码认证

对于密码认证来说,etcd 并不是简单地直接存储明文密码,因为这样安全性太低,一旦数据库泄露,就都知道了。

针对控制面来说,在收到用户添加用户和密码的请求之后,

  • 鉴权模块会使用 bcrpt 库的 blowfish 算法,基于明文密码、随机的加盐 salt,并进行多次迭代 hash(迭代次数是自定义的 cost 次),最终得到一个 hash 值。
  • 之后将加密算法版本、salt 值、cost、hash 值组成一个字符串,作为加密后的密码。
  • 最后,将用户名作为 key,用户名、加密后的密码作为 value,存储到 boltdb 的 AuthUsers bucket 里面。

针对数据面来说,

  • 鉴权模块首先根据请求的用户名,从 boltdb 获取加密后的密码。由于加密后的密码包含了算法版本、salt、cost 等信息。因此,鉴权模块会根据请求中的明文密码,计算出最终的 hash 值,若计算结果与存储一致,那么身份校验通过。

  • 为了提升密码验证的性能,当验证用户密码成功后,会返回一个 Token 字符串给 client,用于表示用户的身份。后续请求携带此 Token,就无需再次进行密码校验。

    etcd 目前支持两种 Token,分别为 Simple Token 和 JWT Token。

    • Simple Token。

      核心原理是当一个用户身份验证通过后,生成一个随机的字符串值 Token 返回给 client,并在内存中使用 map 存储用户和 Token 映射关系。当后续收到用户的请求时,etcd 会从请求中获取 Token 值,通过 map 转换成对应的用户名信息。

      同时生成的每个 Token,都有一个过期时间 TTL 属性,Token 过期后 client 需再次验证身份。通过调整 TTL,可在性能上、安全性上实现平衡。在 etcd v3.4.9 版本中,Token 默认有效期是 5 分钟。

      Simple Token 存在的主要问题是 Simple Token 字符串本身并未含任何有价值信息,对于 client 来说,它无法及时、准确地获取到 Token 过期时间。所以 client 无法提前规避因 Token 失效导致的请求报错。同时需要使用内存存储 Token 和用户名的映射关系。因此 etcd 社区仅建议在开发、测试环境中使用 Simple Token。

    • JWT Token。

      Etcd 还提供了 JWT Token,由于 JWT Token 可自带用户名、版本号、过期时间等描述信息,

      • 一方面 etcd server 不需要保存它。
      • 另一方面 client 可方便、高效的获取到 Token 的过期时间、用户名等信息。

      因此它解决了 Simple Token 的若干不足之处,安全性更高。etcd 社区建议大家在生产环境若使用了密码认证,应使用 JWT Token( --auth-token 'jwt'),而不是默认的 Simple Token。

      下面介绍下 JWT:JWT 是 Json Web Token 缩写,它是一个基于 JSON 的开放标准(RFC 7519)定义的一种紧凑、独立的格式,可用于在身份提供者和服务提供者间,传递被认证的用户身份信息。它由 Header、Payload、Signature 三个对象组成,每个对象都是一个 JSON 结构体。

      第一个对象是 Header,它包含 alg 和 typ 两个字段,alg 表示签名的算法,etcd 支持 RSA、ESA、PS 系列,typ 表示类型就是 JWT。

      {
        "alg": "RS256",
      	"typ": "JWT"
      }
      

      第二对象是 Payload,它表示载荷,包含用户名、过期时间等信息,可以自定义添加字段。

      {
      	"username": username,
      	"revision": revision,
      	"exp": time.Now().Add(t.ttl).Unix()
      }
      

      第三个对象是签名,将 header、payload 使用 base64 url 编码后,再将编码后的字符串用"."连接在一起,最后用我们选择的签名算法比如 RSA 系列的私钥对其计算签名,输出结果即是 Signature。

      signature=RSA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      key)
      

      最终的 JWT Token 内容,就是由 base64UrlEncode(header).base64UrlEncode(payload).signature 组成。

证书认证

密码认证一般使用在 client 和 server 基于 HTTP 协议通信的内网场景中。当对安全有更高要求的时候,需要使用 HTTPS 协议加密通信数据,防止中间人攻击和数据被篡改等安全风险。HTTPS 是利用非对称加密实现身份认证和密钥协商,在使用 HTTPS 协议的时候,需要使用 CA 证书给 client 生成证书才能访问。

Etcd 支持 x509 证书,Etcd 会将客户端 x509 证书中 Subject 字段的 CN 作为用户名。比如下图中,alice 就是客户端发送请求的用户名。

etcd 通过 --client-cert-auth 参数来启用 client 证书认证。

证书认证在稳定性、性能上都优于密码+Token认证。

  • 稳定性上,它不存在 Token 过期、使用更加方便,避免了不少因 Token 失效而触发的 Bug。
  • 性能上,证书认证无需像密码认证一样调用昂贵的密码认证操作(Authenticate 请求),该操作的性能极低。

授权

常用的权限控制方法有 ACL(Access Control List)、ABAC(Attribute-based access control)、RBAC(Role-based access control),而 etcd 采用的是 RBAC 机制。

RBAC 机制由三部分组成,User、Role、Permission。

  • User 表示用户,如 alice。
  • Role 表示角色,它是权限的赋予对象,会包含一系列 Permission。
  • Permission 表示具体权限明细,对于 Etcd 来说,就是对 key 范围在 [key,KeyEnd] 的数据是否具有 READ、WRITE、 READWRITE 等相应权限。

因为一个用户可能拥有成百上千个权限列表,因此 etcd 为了提升权限检查的性能,引入了区间树,会快速检查用户操作的 key 是否在已授权的区间,然后对应的权限是什么,时间复杂度为 O(logN)。

相关操作

# 开启鉴权,此时 etcd 会先要求你创建一个 root 账号,它拥有集群的最高读写权限。
$ etcdctl user add root:root
User root created
$ etcdctl auth enable
Authentication Enabled

# 添加用户 alice
$ etcdctl user add alice:alice --user root:root
User alice created

# put hello=world,带上 alice 用户
$ etcdctl put hello world --user alice:alice

# 创建一个 admin role 
$ etcdctl role add admin  --user root:root
# 分配一个可读写 [hello,helly] 范围数据的权限给 admin role
$ etcdctl role grant-permission admin readwrite hello helly --user root:root
# 将用户 alice 和 admin role 关联起来,赋予 admin 权限给 user
$ etcdctl user grant-role alice admin --user root:root
卷死我
dawnguo 微信支付

微信支付

dawnguo 支付宝

支付宝

  • 本文作者: dawnguo
  • 本文链接: /archives/260
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# Kubernetes # Etcd
Etcd Watch 原理
Etcd Lease 机制介绍
  • 文章目录
  • 站点概览
dawnguo

dawnguo

215 日志
24 分类
37 标签
RSS
Creative Commons
© 2018 — 2025 程序锅
0%