攻防矩阵之ServiceAccount创建

admin 2024年11月11日22:58:27评论2 views字数 12788阅读42分37秒阅读模式

前言

攻防矩阵之ServiceAccount创建

Useraccount 作用是在外部访问的时候使用,给人使用所有的namespace都可以使用 。ServiceAccount是给运行在Pod的程序使用的身份认证,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户;ServiceAccount仅局限它所在的namespace,每个namespace创建时都会自动创建一个default service account;创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。

步骤

ServiceAccount创建

ClusterRole创建

1 由于我们这是学习,所以这里创建一个namespace,而不是在默认的命令空间中创建项目。

[root@master cor0ps-cluster]# kubectl create namespace cor0ps-cluster
namespace/cor0ps-cluster created

2、接下来就是手工创建一个serviceaccount或者直接将serviceaccount绑定到我们前面创建的命令空间。

[root@master cor0ps-cluster]# kubectl create serviceaccount cor0ps-cluster-service-account
serviceaccount/cor0ps-cluster-service-account created

或者

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cor0ps-cluster-service-account
  namespace: cor0ps-cluster
EOF

3、创建一个ClusterRole 

如果一个serviceaccount要访问集群的资源,是需要定义一个能访问哪些操作的角色定义。

cat <<EOF | kubectl apply -f -
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cor0ps-cluster-role
  namespace: cor0ps-cluster
rules:
  - apiGroups:
        - ""
        - apps
        - autoscaling
        - batch
        - extensions
        - policy
        - rbac.authorization.k8s.io
    resources:
      - pods
      - componentstatuses
      - configmaps
      - daemonsets
      - deployments
      - events
      - endpoints
      - horizontalpodautoscalers
      - ingress
      - jobs
      - limitranges
      - namespaces
      - nodes
      - pods
      - persistentvolumes
      - persistentvolumeclaims
      - resourcequotas
      - replicasets
      - replicationcontrollers
      - serviceaccounts
      - services
    verbs: ["get""list""watch""create""update""patch""delete"]
EOF

当然我们如果知道一个cluster-role,我们可以查询该角色定义了哪些操作

[root@master cor0ps-cluster]# kubectl get clusterrole cor0ps-cluster-role -n cor0ps-cluster -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRole","metadata":{"annotations":{},"name":"cor0ps-cluster-role"},"rules":[{"apiGroups":["","apps","autoscaling","batch","extensions","policy","rbac.authorization.k8s.io"],"resources":["pods","componentstatuses","configmaps","daemonsets","deployments","events","endpoints","horizontalpodautoscalers","ingress","jobs","limitranges","namespaces","nodes","pods","persistentvolumes","persistentvolumeclaims","resourcequotas","replicasets","replicationcontrollers","serviceaccounts","services"],"verbs":["get","list","watch","create","update","patch","delete"]}]}
  creationTimestamp: "2023-05-16T13:01:41Z"
  name: cor0ps-cluster-role
  resourceVersion: "55987"
  uid: 61b37f23-6431-47b7-972b-cb10b1cbf2c0
rules:
- apiGroups:
  - ""
  - apps
  - autoscaling
  - batch
  - extensions
  - policy
  - rbac.authorization.k8s.io
  resources:
  - pods
  - componentstatuses
  - configmaps
  - daemonsets
  - deployments
  - events
  - endpoints
  - horizontalpodautoscalers
  - ingress
  - jobs
  - limitranges
  - namespaces
  - nodes
  - pods
  - persistentvolumes
  - persistentvolumeclaims
  - resourcequotas
  - replicasets
  - replicationcontrollers
  - serviceaccounts
  - services
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
  - delete

4、创建一个CluserRole Binding 

现在我们创建好了service account和 clusterRole ,现在需要将它们两个绑定在一起生效。

cat <<EOF | kubectl apply -f -
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cor0ps-cluster-role-binding
subjects:
- namespace: cor0ps-cluster
  kind: ServiceAccount
  name: cor0ps-cluster-service-account
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cor0ps-cluster-role 
EOF

查询刚才创建的clusterrole

[root@master cor0ps-cluster]# kubectl get clusterrolebinding |grep cor0ps
cor0ps-cluster-role-binding                            ClusterRole/cor0ps-cluster-role                                    2m13s

查询该角色绑定的信息

[root@master cor0ps-cluster]# kubectl get clusterrolebinding cor0ps-cluster-role-binding -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"cor0ps-cluster-role-binding"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"cor0ps-cluster-role"},"subjects":[{"kind":"ServiceAccount","name":"cor0ps-cluster-service-account","namespace":"cor0ps-cluster"}]}
  creationTimestamp: "2023-05-16T13:12:12Z"
  name: cor0ps-cluster-role-binding
  resourceVersion: "56934"
  uid: 7dc0aa0b-5923-432f-bbc5-e1cab5cf332b
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cor0ps-cluster-role
subjects:
- kind: ServiceAccount
  name: cor0ps-cluster-service-account
  namespace: cor0ps-cluster

5、使用kubectl来验证serviceaccount角色是否生效 

为了验证clusterrole 绑定是否生效,我们可以使用kubectl自带的 can-i 命令来验证 API 是否具备权限。

[root@master cor0ps-cluster]# kubectl auth can-i get pods --as=system:serviceaccount:cor0ps-cluster:cor0ps-cluster-service-account
yes

[root@master cor0ps-cluster]# kubectl auth can-i create pods --as=system:serviceaccount:cor0ps-cluster:cor0ps-cluster-service-account
yes

[root@master cor0ps-cluster]# kubectl auth can-i delete deployments --as=system:serviceaccount:cor0ps-cluster:cor0ps-cluster-service-account
yes

yes表示有权限操作,no表示无权限操作。

6、使用API接口来验证

[root@master cor0ps-cluster]# kubectl get serviceaccounts -n cor0ps-cluster
NAME                             SECRETS   AGE
cor0ps-cluster-service-account   0         42m
default                          0         45m


[root@master cor0ps-cluster]# kubectl get serviceaccount cor0ps-cluster-service-account -n cor0ps-cluster -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"cor0ps-cluster-service-account","namespace":"cor0ps-cluster"}}
  creationTimestamp: "2023-05-16T12:57:53Z"
  name: cor0ps-cluster-service-account
  namespace: cor0ps-cluster
  resourceVersion: "55641"
  uid: 2085283b-bec4-4179-be26-71b98ed2664e

由于我这里是新版本v1.27.1,serviceaccount token改用mount挂载到文件。https://www.programmingwithwolfgang.com/use-the-tokenrequest-api-to-create-tokens-in-kubernetes/这里为了对比,寻找一个低版本的测试下:发现低于1.24版本的创建了serviceaccount绑定的时候,会自动生成一个token secret类型。

[root@xdm-f-safe-34266 role]# kubectl get secrets -n cor0ps-cluster
NAME                                         TYPE                                  DATA   AGE
cor0ps-cluster-service-account-token-vqgnv   kubernetes.io/service-account-token   3      73s
default-secret                               kubernetes.io/dockerconfigjson        1      70s
default-token-9xxmw                          kubernetes.io/service-account-token   3      87s
[root@xdm-f-safe-34266 role]# kubectl version --short
Client Version: v1.21.4
Server Version: v1.21.7-r0-daily-build

高于1.24版本是不会自动生成serviceaccount token

[root@icsltaochao-docker cor0ps]# kubectl get secrets -n cor0ps-cluster
NAME             TYPE                             DATA   AGE
default-secret   kubernetes.io/dockerconfigjson   1      4m21s
paas.elb         cfe/secure-opaque                3      4m21s
[root@icsltaochao-docker cor0ps]# kubectl version --short
Client Version: v1.25.3

那么在高版本我们需要给serviceaccount 绑定生成一个token。这里测试使用的namepsace 是cor0ps-cluster。

cat <<EOF | kubectl create -f - -v=6
apiVersion: v1
kind: Secret
metadata:
  name: cor0ps-user-token
  namespace: cor0ps-cluster  //这里一定要指定,默认是default
  annotations:
    kubernetes.io/service-account.name: cor0ps-cluster-service-account
type: kubernetes.io/service-account-token
EOF

现在我们再来获取下我们创建的token

[xxx cor0ps]# kubectl get secrets
NAME                TYPE                                  DATA   AGE
cor0ps-user-token   kubernetes.io/service-account-token   3      54s

[root@icsltaochao-docker cor0ps]# kubectl get secret cor0ps-user-token -o yaml
apiVersion: v1
data:
  ca.crt: xxxx
  token: ZXlKa...=
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: cor0ps-cluster-service-account
    kubernetes.io/service-account.uid: 5c462abc-060d-43b5-a84b-2bc0ecb73675
  creationTimestamp: "2023-05-17T03:19:05Z"
  name: cor0ps-user-token
  namespace: default
  resourceVersion: "25076"
  uid: 71e36a06-3d4b-4d35-a4c3-81a57dea7bc3
type: kubernetes.io/service-account-token

通过命令解析出token值

SECRET_NAME="cor0ps-user-token"
TOKEN=$(kubectl get secret ${SECRET_NAME} -o jsonpath='{$.data.token}' | base64 -d | sed $'s/$/\n/g')
echo $TOKEN

然后获取apiserver的地址

[xxx cor0ps]# kubectl get endpoints
NAME         ENDPOINTS                                                AGE
kubernetes   192.168.0.109:5444,192.168.0.193:5444,192.168.0.7:5444   100m

构造API请求

curl -k https://API-SERVER-IP/api/v1/namespaces?limit=500 -H "Authorization: Bearer $TOKEN"

成功访问。

Role 创建

1、单独创建一个测试role的命令空间

[cor0ps]# kubectl create namespace cor0ps-role
namespace/cor0ps-role created

2、创建serviceaccount和命令空间绑定

apiVersion: v1
kind: ServiceAccount
metadata:
  name: cor0ps-role-service-account
  namespace: cor0ps-role

3、创建role的定义

cat <<EOF | kubectl apply -f -
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: cor0ps-role
  namespace: cor0ps-role
rules:
  - apiGroups:
        - ""
        - apps
        - autoscaling
        - batch
        - extensions
        - policy
        - rbac.authorization.k8s.io
    resources:
      - pods
      - componentstatuses
      - configmaps
      - daemonsets
      - deployments
      - events
      - endpoints
      - horizontalpodautoscalers
      - ingress
      - jobs
      - limitranges
      - namespaces
      - nodes
      - pods
      - persistentvolumes
      - persistentvolumeclaims
      - resourcequotas
      - replicasets
      - replicationcontrollers
      - serviceaccounts
      - services
    verbs: ["get""list""watch""create""update""patch""delete"]
EOF

4、创建role 和 serviceaccount的绑定

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: cor0ps-role-rolebinding
  namespace: cor0ps-role
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: cor0ps-role
subjects:
- namespace: cor0ps-role
  kind: ServiceAccount
  name: cor0ps-role-service-account

5、验证前面配置的role的权限 这里先拉起一个pod。

cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Pod
metadata:
  name: role-test
  namespace: cor0ps-role
spec:
  containers:
  - image: bibinwilson/docker-kubectl:latest
    name: kubectl
  serviceAccountName: cor0ps-role-service-account
EOF

进入容器获取到token 和apiserver的ip,我们访问会出现如下

[root@master cor0ps-role]# API="192.168.133.5:6443"
[root@master cor0ps-role]# curl -k https://$API/api/v1/namespaces?limit=500 -H "Authorization: Bearer $TOKEN"
{
  "kind""Status",
  "apiVersion""v1",
  "metadata": {},
  "status""Failure",
  "message""namespaces is forbidden: User "system:serviceaccount:cor0ps-role:cor0ps-role-service-account" cannot list resource "namespaces" in API group "" at the cluster scope",
  "reason""Forbidden",
  "details": {
    "kind""namespaces"
  },
  "code": 403
}
[root@master cor0ps-role]# kubectl auth can-i get pods --as=system:serviceaccount:cor0ps-crolecor0ps-crole-service-account
no

不能遍历所有的namespaces或pods ,那么我们建立的这个role具体有什么作用呢

[root@master cor0ps-role]# curl -k https://192.168.133.5:6443/api/v1/namespaces/cor0ps-role/pods?limit=500 -H "Authorization: Bearer $TOKEN"
{
  "kind""PodList",
  "apiVersion""v1",
  "metadata": {
    "resourceVersion""64210"
  },
  "items": [
    {
      "metadata": {
        "name""role-test",
        "namespace""cor0ps-role",
        "uid""08eb9b68-a2a6-4725-9ead-6f8acf9c35de",
        "resourceVersion""61467",
        "creationTimestamp""2023-05-17T12:58:46Z",
        "annotations": {
          "kubectl.kubernetes.io/last-applied-configuration""{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"role-test","namespace":"cor0ps-role"},"spec":{"containers":[{"image":"bibinwilson/docker-kubectl:latest","name":"kubectl"}],"serviceAccountName":"cor0ps-role-service-account"}}n"
        },

从这里可以看的出实际role角色只能限定在某个对应绑定的namespace上。那么我们再使用该绑定的token 去访问未绑定的namespace cor0ps-cluster 看下访问结果。

[root@master cor0ps-role]# curl -k https://192.168.133.5:6443/api/v1/namespaces/cor0ps-cluster/pods?limit=500 -H "Authorization: Bearer $TOKEN"
{
  "kind""Status",
  "apiVersion""v1",
  "metadata": {},
  "status""Failure",
  "message""pods is forbidden: User "system:serviceaccount:cor0ps-role:cor0ps-role-service-account" cannot list resource "pods" in API group "" in the namespace "cor0ps-cluster"",
  "reason""Forbidden",
  "details": {
    "kind""pods"
  },
  "code": 403
}

结果是不可以的。

如何根据serviceaccount 反推到具体的role 角色定义。

kubectl get serviceaccounts -A -v=6
kubectl get rolebindings,clusterrolebindings   --all-namespaces    -o custom-columns='KIND:kind,NAMESPACE:metadata.namespace,NAME:metadata.name,SERVICE_ACCOUNTS:subjects[?(@.kind=="ServiceAccount")].name' |grep xxxx

附录

https://devopstales.github.io/kubernetes/k8s-user-accounts/

原文始发于微信公众号(Web安全):攻防矩阵之ServiceAccount创建

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月11日22:58:27
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   攻防矩阵之ServiceAccount创建https://cn-sec.com/archives/1844793.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息