Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证

这篇具有很好参考价值的文章主要介绍了Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、概述

  在 Kubernetes 官方手册中给出了 “用户” 的概念,Kubernetes 集群中存在的用户包括 “普通用户” 与 “ServiceAccount”, 但是 Kubernetes 没有普通用户的管理方式,通常只是将使用集群根证书签署的有效证书的用户都被视为合法用户。

  那么对于使得 Kubernetes 集群有一个真正的用户系统,就可以根据上面给出的概念将 Kubernetes 用户分为“内部用户”与“外部用户”。如何理解内部与外部用户呢?实际上就是由 Kubernetes 管理的用户,即在 kubernetes 定义用户的数据模型这种为 “内部用户” ,正如 ServiceAccount;反之,非 Kubernetes 托管的用户则为 “外部用户”, 这种概念也更好的对 kubernetes 用户的阐述。

  对于外部用户来说,实际上 Kubernetes 给出了多种用户概念,例如:

  • 拥有 kubernetes 集群证书的用户
  • 拥有 Kubernetes 集群 token 的用户(--token-auth-file指定的静态 token)
  • 用户来自外部用户系统,例如 OpenID,LDAP,QQ connect, google identity platform 等

      本文不过多介绍Kubernetes外部用户认证,主要讲解Kubernetes内部用户ServiceAccount的认证方式,即大部分Pod默认的认证方式(Pod和APIServer之间如果没有配置基于CA根证书签名的双向数字证书方式进行认证的话,则默认通过Token方式进行认证)。

注意:在之前博文中讲解过拥有kubernetes集群证书的用户的认证方式,详情见《Kubernetes客户端认证——基于CA证书的双向认证方式》。

2、基于ServiceAccount的JWTToken认证

2.1 ServiceAccount定义

ServiceAccount(服务帐户)与Namespace绑定,关联一套凭证,Pod创建时挂载Token,从而允许与API Server之间调用。ServiceAccount同样是Kubernetes中的资源,与Pod、ConfigMap类似,且作用于独立的命名空间,也就是ServiceAccount是属于命名空间级别的,创建命名空间时会自动创建一个名为default的ServiceAccount。

使用下面命令可以查看ServiceAccount。

[root@node1 ~]# kubectl get sa
NAME                SECRETS   AGE
default             1         356d

同时Kubernetes还会为ServiceAccount自动创建一个Token,使用下面命令可以查看到。

[root@node1 ~]# kubectl describe sa default 
Name:                default
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   default-token-p4l9w
Tokens:              default-token-p4l9w
Events:              <none>

在Pod的定义文件中,可以用指定帐户名称的方式将一个ServiceAccount赋值给一个Pod,如果不指定就会使用默认的ServiceAccount。当API Server接收到一个带有认证Token的请求时,API Server会用这个Token来验证发送请求的客户端所关联的ServiceAccount是否允许执行请求的操作。

注意:

  • 1.21以前版本的集群中,Pod中获取Token的形式是通过挂载ServiceAccount的Secret来获取Token,这种方式获得的Token是永久的。该方式在1.21及以上的版本中不再推荐使用,并且根据社区版本迭代策略,在1.25及以上版本的集群中,ServiceAccount将不会自动创建对应的Secret。

    1.21及以上版本的集群中,直接使用TokenRequest API获得Token,并使用投射卷(Projected Volume)挂载到Pod中。使用这种方法获得的Token具有固定的生命周期,并且当挂载的Pod被删除时这些Token将自动失效。详情请参见Token安全性提升说明。

  • 如果您在业务中需要一个永不过期的Token,您也可以选择手动管理ServiceAccount的Secret。尽管存在手动创建永久ServiceAccount Token的机制,但还是推荐使用TokenRequest的方式使用短期的Token,以提高安全性。

2.2 创建ServiceAccount

使用如下命令就可以创建ServiceAccount:

[root@node1 ~]# kubectl create serviceaccount sa-example
serviceaccount/sa-example created
[root@node1 ~]# kubectl get sa
NAME                SECRETS   AGE
default             1         356d
sa-example          1         6s

可以看到已经创建了与ServiceAccount相关联的Token。

[root@node1 ~]# kubectl describe sa sa-example
Name:                sa-example
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   sa-example-token-42nbt
Tokens:              sa-example-token-42nbt
Events:              <none>

查看Secret的内容,可以发现ca.crt、namespace和token三个数据。

[root@node1 ~]# kubectl describe secret sa-example-token-42nbt
Name:         sa-example-token-42nbt
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: sa-example
              kubernetes.io/service-account.uid: 5c67e9c7-0b12-44ae-a97e-f2ee4cd061b0

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1066 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6InpKM2o1WXg2b1pwQ0lyTjNWVU4wUjUzMTZuamt0LVZEQlNqbG5HLWNxdUUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNhLWV4YW1wbGUtdG9rZW4tNDJuYnQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoic2EtZXhhbXBsZSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjVjNjdlOWM3LTBiMTItNDRhZS1hOTdlLWYyZWU0Y2QwNjFiMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OnNhLWV4YW1wbGUifQ.FlL0EAeNYOqNpCmBG5QU0qAbGIVHjTP3hVMOL8nmiawmZsitSDupKrdbpIjFgS3VOTR8GZfZCnCnVI7fE0ZkZzt6kW7ILTRIiNbmedScI4w_FiSbGI-MX48HJAIgF0hrdJ3_Rc30-Or-fMxlligcO08OpSQrBT20J4LR6NM4B-r_s83b7Rwm7F95GWc5rmYZje1uRJfRuzqBwV4PLT5Ph7u_XDn8WS1XXWagq5qioySFV1Xg9Lb9nHXVNmTL2g0E2_RDqUFj-tsns8Xj3B9Yvm4CH5uS6PbV0UsdFlm-mCOF4vinDHSP4mH6CSBWyzRnl9vF7hbfNzW96rIKKSJ9CA 

注意:只有在1.23及之前版本的集群中,ServiceAccount才会自动创建Secret。

2.3 在Pod中使用ServiceAccount

Pod中使用ServiceAccount非常方便,只需要指定ServiceAccount的名称即可。

apiVersion: v1
kind: Pod
metadata:
  name: sa-example
spec:  
  serviceAccountName: sa-example
  containers:
  - image: nginx:alpine             
    name: container-0               
    resources:                      
      limits:
        cpu: 100m
        memory: 200Mi
      requests:
        cpu: 50m
        memory: 100Mi

创建并查看这个Pod,可以看到Pod挂载了sa-example-token-c7bqx,即Pod使用这个Token来做认证。

[root@node1]# kubectl apply -f test-sa.yaml 
pod/sa-example created

[root@node1 test]# kubectl get pods
NAME                                              READY   STATUS    RESTARTS   AGE
sa-example                                        1/1     Running   0          32s

[root@node1]#  kubectl describe pod sa-example
...
Containers:
  sa-example:
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from sa-example-token-42nbt (ro)

注意: 通过这个方式,您可以了解Pod的认证机制,但在实际使用中,出于安全性考虑,1.21及以上版本的集群中Pod中默认挂载的Token是临时的。

进入Pod内部,还可以看到对应的文件,如下所示:

[root@node1 ~]# kubectl exec -it sa-example /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /run/secrets/kubernetes.io/serviceaccount
/run/secrets/kubernetes.io/serviceaccount # ls
ca.crt     namespace  token

如上,在容器应用中,就可以使用ca.crt和Token来访问APIServer。

2.4 基于token访问APIServer

下面来验证一下认证是否能生效。在Kubernetes集群中,默认为API Server创建了一个名为kubernetes的Service,通过这个Service可以访问API Server。

[root@node1 ~]# kubectl get svc
NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                
kubernetes                   ClusterIP   10.233.0.1      <none>        443/TCP             356d

进入Pod,使用curl命令直接访问会报以下错误:

[root@node1 ~]# kubectl exec -it sa-example /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # curl https://kubernetes
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
/ # 

注意:报错原因是因为curl客户端和Kube-Apiserver服务端建立的是SSL/TLS单向连接,curl和Kube-Apiserver建立连接过程中,Kube-Apiserver会将服务端证书返回给curl客户端,而curl客户端没有指定ca.crt,因此无法验证服务器的合法性,因此无法建立与它的安全连接。

使用ca.crt和Token做认证,先将ca.crt放到CURL_CA_BUNDLE这个环境变量中,curl命令使用CURL_CA_BUNDLE指定证书;再将Token的内容放到TOKEN中,然后带上TOKEN访问API Server。 

/ # export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
/ # TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
/ # curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:default:sa-example\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}/ # 

可以看到,已经能够通过认证了,但是API Server返回的是cannot get path \"/\"",表示没有权限访问,这说明还需要得到授权后才能访问,接下来为default命名空间下的ServiceAccount  sa-example关联Role使其能够获取Pod资源。

首先创建Role,Role的定义非常简单,指定namespace,然后就是rules规则。如下面示例中的规则就是允许对default命名空间下的Pod进行GET、LIST操作。

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default                          # 命名空间
  name: role-example
rules:
- apiGroups: [""]
  resources: ["pods"]                         # 可以访问pod
  verbs: ["get", "list"]                      # 可以执行GET、LIST操作

有了Role之后,就可以将Role与具体的用户绑定起来,实现这个的就是RoleBinding了。如下所示:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rolebinding-example
  namespace: default
subjects:                                 # 指定用户
- kind: ServiceAccount                    # ServiceAccount
  name: sa-example
  namespace: default
roleRef:                                  # 指定角色
  kind: Role
  name: role-example
  apiGroup: rbac.authorization.k8s.io

在Kubernetes集群apply Role和Rolebind文件,现在再进入到sa-example这个Pod,使用curl命令通过API Server访问资源来验证权限是否生效。

/ # export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
/ # TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
/ # curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/pods
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/default/pods",
    "resourceVersion": "10377013"
  },
  "items": [
    {
      "metadata": {
        "name": "sa-example",
......

返回结果正常,说明sa-example现在有LIST Pod的权限了。

注意 1:本示例中,sa-example Pod通过HTTPS单向认证方式与Kube-Apiserver服务端建立连接后,进入Kube-Apiserver认证过滤器链(默认支持CA认证和Token认证两种身份验证方式,因为客户端证书为空,所以不会执行CA认证过滤器逻辑),如果请求中包含Authorization头部,并且其值是以Bearer开头的Token,则进入Token认证过滤器逻辑,对JWT Token进行验证,如果Token未过期且签名有效,则认证成功,并从中获取Pod所使用的ServiceAccount的用户信息。认证成功后,进入Kube-Apiserver授权阶段,如果请求被授权,则继续处理;否则,Kube-Apiserver会返回HTTP 403未授权错误。

注意 2:本示例中,sa-example Pod和 API Server 之间建立了一个加密的 SSL/TLS 连接(HTTPS单向认证方式),所有的通信都会经过加密传输,包括客户端请求中的 token 信息和 Kube-Apiserver 的响应。这样可以确保通信过程中的安全性,同时防止任何未经授权的访问和攻击。HTTPS单向认证步骤如下:

  1. 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端。
  2. 服务端将自己的公钥证书(server.crt)发送给客户端。
  3. 客户端通过自己的根证书(ca.crt)验证服务端的公钥证书(server.crt)的合法性,取出服务端公钥。(如果验证公钥证书失败,则中断HTTPS连接)
  4. 客户端生成密钥R,用服务端公钥去加密它形成密文,发送给服务端。
  5. 服务端用自己的私钥(server.key)去解密这个密文,得到客户端的密钥R。
  6. 服务端和客户端使用密钥R进行通信。
Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证

注意 3: Kube-Apiserver tls客户端认证配置为RequestClientCert(客户端请求可以不发送客户端证书),即可以不使用SSL/TLS加密方式或仅使用SSL/TLS单向认证方式或使SSL/TLS双向认证方式与Kube-Apiserver服务端建立连接,所以不使用SSL/TLS加密方式方式认证与Kube-Apiserver服务端建立连接也是可以的。

/ # curl -k  https://kubernetes/api/v1/namespaces/default/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:anonymous\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
/ # TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
/ # curl -k -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/pods
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/namespaces/default/pods",
    "resourceVersion": "10377013"
  },
  "items": [
    {
      "metadata": {
        "name": "sa-example",
......
注意 4:Kube-Apiserver服务端监听的是tls端口,如果使用http方式访问是不行的(对HTTPS服务发起HTTP请求会报请求方式错误,Client sent an HTTP request to an HTTPS server.)。
/ # TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
/ # curl -k -H "Authorization: Bearer $TOKEN" http://kubernetes/api/v1/namespaces/default/pods
curl: (52) Empty reply from server

3、总结

在 Kubernetes 中,Pod客户端和Kube-Apiserver服务端进行交互时,使用 token 进行身份验证的请求会使用 SSL/TLS 加密进行保护。具体来说,使用 token 进行身份验证的请求流程如下:

  1. 客户端使用提前生成好的 token 发起请求,将 token 附加在请求的 Authorization 头部。

  2. 客户端会首先与 API Server 建立一个加密的 SSL/TLS 连接,以保护通信的安全性。

  3. Kube-Apiserver 收到请求后,会对 token 进行验证,如果验证通过,进入Kube-Apiserver授权阶段,如果请求被授权,则继续处理;否则,Kube-Apiserver会返回HTTP 403未授权错误。

在这个过程中,客户端和 API Server 之间建立了一个加密的 SSL/TLS 连接,所有的通信都会经过加密传输,包括客户端请求中的 token 信息和 API Server 的响应。这样可以确保通信过程中的安全性,同时防止任何未经授权的访问和攻击。

需要注意的是,虽然使用 token 进行身份验证的请求会经过 SSL/TLS 加密进行保护,但是 SSL/TLS 加密并不能完全防止所有的安全威胁,因此在实际使用中,仍然需要采取其他安全措施来保障 Kubernetes 环境的安全性。

参考:ServiceAccount

参考:深入理解 Kubernetes 中的用户与身份认证授权文章来源地址https://www.toymoban.com/news/detail-410774.html

到了这里,关于Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Security—OAuth2 客户端认证和授权

    关于 JWT Bearer 客户端认证的进一步详情,请参考OAuth 2.0客户端认证和授权许可的 JSON Web Token (JWT)简介。 JWT Bearer 客户端认证的默认实现是  NimbusJwtClientAuthenticationParametersConverter ,它是一个  Converter ,通过在  client_assertion  参数中添加签名的JSON Web Token(JWS)来定制令牌请求

    2024年02月08日
    浏览(50)
  • 【Kafka】Kafka客户端认证失败:Cluster authorization failed.

    kafka客户端是公司内部基于spring-kafka封装的 spring-boot版本:3.x spring-kafka版本:2.1.11.RELEASE 集群认证方式:SASL_PLAINTEXT/SCRAM-SHA-512 经过多年的经验,以及实际验证,配置是没问题的,但是业务方反馈用相同的配置,还是报错! 封装的kafka客户端版本过低,高版本的配置项:secu

    2024年01月17日
    浏览(51)
  • 【PG】PostgreSQL客户端认证pg_hba.conf文件

    目录 文件格式  连接类型(TYPE) 数据库(database) 用户(user) 连接地址(address) 格式 IPv4 IPv6 字符 主机名 主机名后缀 IP-address/IP-mask auth-method trust reject scram-sha-256 md5 password gss sspi ident peer ldap radius cert pam bsd auth-options 示例 用户在连接到PG数据库之前首先要经过文件的验证,可以

    2024年02月08日
    浏览(40)
  • Zookeeper中的客户端配置认证(zoo_client.conf)

    Zookeeper中的客户端配置认证可以使用两种方法:digest和Kerberos。 客户端鉴权配置 该配置是用于启用Zookeeper SASL认证提供程序的选项,它是Zookeeper中一种基于Kerberos的身份验证方式。SASL(Simple Authentication and Security Layer)是一种通用的安全联接层协议,通常用于安全认证。 具体

    2024年02月13日
    浏览(54)
  • MQTT EMQX v5.0版本监听客户端上下线通知、认证、授权

    之前在自助洗车项目中使用emqx的是4.4版本,最新部署的时候采用了5.0。 旧版本认证、上下线通知等都需要开启插件,在配置文件修改,操作比较麻烦。 升级后增强了dashboard(web管理界面),好多插件都成为内置插件,无需开启,且很多操作无需进入配置文件,直接在web即可

    2024年02月09日
    浏览(44)
  • Kafka增加安全验证安全认证,SASL认证,并通过spring boot-Java客户端连接配置

    公司Kafka一直没做安全验证,由于是诱捕程序故需要面向外网连接,需要增加Kafka连接验证,保证Kafka不被非法连接,故开始研究Kafka安全验证 使用Kafka版本为2.4.0版本,主要参考官方文档 官网对2.4版本安全验证介绍以及使用方式地址: https://kafka.apache.org/24/documentation.html#secu

    2024年02月01日
    浏览(62)
  • 07 mysql5.6.x docker 启动, 无 config 目录导致客户端连接认证需要 10s

    呵呵 最近再一次 环境部署的过程中碰到了这样的一个问题 我基于 docker 启动了一个 mysql 服务, 然后 挂载出了 数据目录 和 配置目录, 没有手动复制配置目录出来, 所以配置目录是空的 然后 我基于 docker 启动了一个 nacos, 配置数据库设置为上面的这个 mysql 然后 启动 nacos, 启动

    2024年02月12日
    浏览(38)
  • 在Linux上使用openssl生成CA认证文件并为服务器和客户端颁发CA签名证书

    本文基于Linux上CentOS 7版本配合openssl与mod_ssl(需要使用yum下载)进行配置演示 目录 一.生成认证主要流程 1.虚拟出一个CA认证机构,为其生成公私钥以及自签证书 2.生成服务器方私钥,发送包含服务器方公私钥的申请文件给CA机构请求签发证书 3.生成客户端方私钥,发送包含服务

    2024年02月16日
    浏览(50)
  • Spring Boot 最新版3.x 集成 OAuth 2.0实现认证授权服务、第三方应用客户端以及资源服务

    Spring Boot 3 已经发布一段时间,网上关于 Spring Boot 3 的资料不是很多,本着对新技术的热情,学习和研究了大量 Spring Boot 3 新功能和新特性,感兴趣的同学可以参考 Spring 官方资料全面详细的新功能/新改进介绍 Spring 版本升级到6.x JDK版本至少17+ … 新特性有很多,本文主要针对

    2024年02月02日
    浏览(68)
  • 三:基于TCP的服务端/客户端

    其中四层模型说的就是TCP(UDP)/IP协议栈 并列图片 listen详解 当客户端发送连接请求时,并不一定能立即连接到。尽管此时服务端处于等待连接请求状态(listen),但是由于系统正忙,此连接请求需要进入连接请求等待队列,listen第二个参数便是设置此等待队列的大小。 accept函数

    2024年01月20日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包