如何爲K8S生產系統配置安全管理?

PX-Security:針對Kubernetes持久卷的多租戶授權、身份驗證和RBAC

PX-Security演示視頻鏈接
https://v.qq.com/x/page/s30609pfmuq.html

安全對於企業來說至關重要,對於運行在Kubernetes上的基於微服務的應用來說更是如此。
Kubernetes提供RBAC授權,根據不同角色設定,管理Kubernetes內部特定資源的訪問權限。這些機制對於管理Kubernetes的特定對象(如服務、命名空間、配額等)的訪問權限非常有用。但命名空間和pod的安全策略本身,不足以限制誰有權限可以請求更改底層數據管理系統。

許多企業通過CNI或CSI等API,調用其他的平臺能力來提供網絡和存儲基礎。Kubernetes所缺乏的是將RBAC擴展到這些系統的能力,需要外部系統來確保授權和認證功能的實現。

這就是爲什麼Portworx與Kubernetes攜手,通過對支撐Kubernetes中PVCs的持久卷,進行訪問角色控制,來提供RBAC、加密和控制權限,這將創建一個無縫的保護層,爲您的PVCs提供以下保護:

  1. 同一命名空間中的用戶可以受到其角色的限制,比如他們可以具有讀、寫、管理員或其他定義的訪問權限。
    
  2. 用戶可以通過Token自動進行身份驗證,這樣審計請求的授權就可以針對特定命名空間來進行。
    
  3. 可以將用戶置於基於租戶的命名空間中,從而爲訪問PVCs提供安全的多租戶。
    
  4. 即使用戶看到存儲類,也不意味着他們被授權創建PVC。
    
  5. 將Portworx RBAC與加密一起使用,意味着數據在host上是安全的,命名空間內的非授權用戶不能訪問數據。
    
  6. 如果一個請求來自Kubernetes外部而沒有Token,它將被阻止。
    

要深入瞭解Portworx能爲您的Kubernetes平臺提供什麼,可以查看Portworx網站上的安全參考體系架構。我們將重點討論一些主題,比如如何設置PX-Security,以及如何使用Token對具有相應持久卷訪問權限的角色用戶進行身份驗證。
首先,Portworx通過使用Token支持RBAC。在本文中,PX-Security將使用存儲在Kubernetes Secrets中的Token,這些Token提供了最靈活的操作,且不犧牲任何安全性。


開始吧!

在我們討論什麼是Token以及如何使用它之前,有一點需要注意,對Portworx的每個請求都是使用存儲在Token中的信息進行身份驗證和授權的。其中包含關於用戶及其角色所需所有相關的驗證和簽名的信息。因此,我們配置了PX-Security後,我們會創建Token。

讓我們來配置PX-Security來達到安全性。請訪問 https://central.portworx.com,

點擊安裝並運行。填寫安裝程序要求的信息,完成後下載你的YAML文件,將文件保存以便後續做編輯。

接下來,我們將創建用於PX-Security的安全共享的Secrets。我們必須首先創建這些共享的Secrets,因爲存儲管理員將使用它們來生成和驗證Token。出於安全原因,這些數據被存儲在Kube-system命名空間中的Kubernetes Secrets中,只有少量的管理員和應用程序可以訪問該命名空間。

PORTWORX_AUTH_SYSTEM_KEY=$(cat /dev/urandom | base64 | fold -w 65 | head -n 1)
PORTWORX_AUTH_STORK_KEY=$(cat /dev/urandom | base64 | fold -w 64 | head -n 1)
PORTWORX_AUTH_SHARED_SECRET=$(cat /dev/urandom | base64 | fold -w 64 | head -n 1)

運行以下命令將這些值放入Kubernetes Secret中:

kubectl -n kube-system create secret generic pxkeys \
    --from-literal=system-secret=$PORTWORX_AUTH_SYSTEM_KEY \
    --from-literal=stork-secret=$PORTWORX_AUTH_STORK_KEY \
    --from-literal=shared-secret=$PORTWORX_AUTH_SHARED_SECRET

您可以使用以下命令測試Kubernetes中的共享-secret。

kubectl -n kube-system get secret pxkeys -o json | jq -r '.data."shared-secret"' | base64 -d

打開您的YAML文件,找到PortworxDaemonset,可以看args, 在image:portworx/oci-monitor下。這裏我們將添加安全參數(粗體)和PX-Security需要的Secrets:

- name: portworx
  image: portworx/oci-monitor:2.1.5
  imagePullPolicy: Always
  args:
    ["-c", "px-cluster",
     "-s", "/dev/xvdf",
     "-secret_type", "k8s",
     "-b",
     "-x", "kubernetes",
     "-jwt_issuer", "example-domain.com"]
  env:
    - name: "AUTO_NODE_RECOVERY_TIMEOUT_IN_SECS"
      value: "1500"
    - name: "PX_TEMPLATE_VERSION"
      value: "v4"
    - name: "PORTWORX_AUTH_JWT_SHAREDSECRET"
      valueFrom:
        secretKeyRef:
          name: pxkeys
          key: shared-secret
    - name: "PORTWORX_AUTH_SYSTEM_KEY"
      valueFrom:
        secretKeyRef:
          name: pxkeys
          key: system-secret
   - name: "PORTWORX_AUTH_STORK_KEY"
     valueFrom:
       secretKeyRef:
          name: pxkeys
          key: stork-secret

我們還需要找到Stork部署和編輯環境以包含我們的共享secret。見下文。

     containers:
  - command:
    - /stork
    - --driver=pxd
    - --verbose
    - --leader-elect=true
    - --health-monitor-interval=120
    imagePullPolicy: Always
    image: openstorage/stork:2.2.5
    env:
    - name: "PX_SERVICE_NAME"
      value: "portworx-api"
    - name: "PX_SHARED_SECRET"
      valueFrom:
         secretKeyRef:
            name: pxkeys
            key: stork-secret

完成這兩個步驟後,保存YAML文件。現在,我們需要創建我們在Portworx安裝YAML中引用的共享Secret。

接下來,使用下載和編輯過的YAML文件創建Portworx集羣。

$ kubectl apply-f px-sec-cluster-spec.yaml
$ kubectl get po -n kube-system -l name=portworx
NAME             READY STATUS RESTARTS   AGE
portworx-4vmcx   1/1 Running 0          3m54s
portworx-hwrxh   1/1 Running 0          3m54s
portworx-rbqzk   1/1 Running 0          3m54s

用戶和Token

我們需要定義幾個用戶併爲他們生成Token。通常,這些用戶有分配給他們的屬性,這些屬性定義了他們的用戶類型。

首先,我們將創建一個存儲管理員,該管理員具有全部權限。這樣的管理員應該只有一兩個。

使用以下內容創建一個名爲admin.yaml的文件:

name: Storage Administrator
email: [email protected]
sub: [email protected]/storageadmin
roles: ["system.admin"]
groups: ["*"]

接下來,我們將創建一個Kubernetes用戶,該用戶作爲一個驗證客戶,Kubernetes允許該用戶與Portworx交互,並且這些請求來自Kubernetes。您的存儲管理員需要設置此用戶。

使用以下內容創建一個名爲kubernetes.yaml的文件:

name: Kubernetes
email: [email protected]
sub: [email protected]/kubernetes
roles: ["system.user"]
groups: ["kubernetes"]

最後,我們將創建一個僅能看 (view-only) 權限的用戶,用於演示Portworx如何限制對底層數據管理API的訪問。

使用以下內容創建一個名爲viewer.yaml的文件:

name: Viewer
email: [email protected]
sub: [email protected]/viewer
roles: ["system.view"]
groups: ["viewers"]

注意:Sub標記是該用戶的唯一標識符,根據JWT標準,不能與其他Token共享。這個值被Portworx用來跟蹤資源的所有權。如果電子郵件也用作唯一Sub標識符,請確保它不被任何其他Token使用。

請注意:有一個用戶的角色是system.admin,另一個用戶的角色是system.user,最後一個用戶的角色是system.view。這些角色在PX-Security中是默認的,但也可以根據需要創建其他角色。我們來演示用戶如何使用Portworx資源,如創建或刪除卷。這跟該用戶在Kubernetes RBAC的配置無關。

也就是說,具有system.view的用戶也許能夠在Kubernetes中內列出和創建PVC對象,但如果他們試圖直接使用Portworx創建卷,將會失敗。我們還將演示,爲什麼能夠創建PVC對象的用戶在此安全模式中實際上無法獲得PV,除非該用戶擁有由存儲管理員配置的有效Token,來驗證其角色和權限。

配置好了這些具備相關權限的用戶,我們就可以使用我們的共享Secret和Portworx客戶端工具pxctl,爲這些用戶生成自簽名證書。

注意:您可以創建自己的應用來生成Token,也可以基於我們的開源golang示例程序openstorage-sdk-auth

在這個場景中,我們將使用共享Secret和pxctl auth token generate命令。讓我們爲上述兩個用戶創建Token。

首先,獲取共享Secret。

PORTWORX_AUTH_SHARED_SECRET=$(kubectl -n kube-system get secret pxkeys -o json \
    | jq -r '.data."shared-secret"' \
    | base64 -d)

接下來,配置Admin Token。首先是SSH,到Portworx節點,這樣就可以使用pxctl命令。

$ PX_POD=$(kubectl get pods -l name=portworx -n kube-system -o jsonpath='{.items[0].metadata.name}')
$ kubectl exec -it -n kube-system $PX_POD  bash

然後,使用admin.yaml和共享Secret創建admin Token。

注意:確保將auth_config文件和PORTWORX_AUTH_SHARED_SECRET 複製到正在使用pxctl的Portworx容器中。

ADMIN_TOKEN=$(/opt/pwx/bin/pxctl auth token generate \
   --auth-config=admin.yaml \
   --issuer=example-domain.com \
   --shared-secret=$PORTWORX_AUTH_SHARED_SECRET \
   --token-duration=1y)
$ pxctl context create admin --token $ADMIN_TOKEN

接下來,配置Kubernetes Token。

KUBE_TOKEN=$(/opt/pwx/bin/pxctl auth token generate \
   --auth-config=kubernetes.yaml \
   --issuer=example-domain.com \
   --shared-secret=$PORTWORX_AUTH_SHARED_SECRET \
   --token-duration=1y)

接下來,配置Viewer token。

VIEWER_TOKEN=$(/opt/pwx/bin/pxctl auth token generate \
   --auth-config=viewer.yaml \
   --issuer=example-domain.com \
   --shared-secret=$PORTWORX_AUTH_SHARED_SECRET \
   --token-duration=1y)
$ pxctl context create viewer --token $VIEWER_TOKEN

現在我們已經創建了用戶環境(Context),比如Portworx的Kubectl環境,來供兩個用戶使用,我們可以作爲其中一個用戶與Portworx系統進行交互。

注意,您可以使用$pxctl contextlist列出所有環境:

$ pxctl context set viewer
$ pxctl volume create --size 5 myvol
VolumeCreate: Access denied to roles: [system.view]

發生了什麼?請記住,我們爲具有system.view角色的Viewer設置了用戶環境。這是Portworx的默認角色,只能運行只讀命令,不具備寫操作的權限,因此訪問被拒絕。

如何與Kubernetes一起使用?

爲了讓Kubernetes的用戶使用PX-Security,用戶必須在向集羣發出請求時使用自己的Token。一種方法是讓管理員在Kubernetes存儲類中配置Token。管理員可以在Portworx命名空間中名爲px-k8-user的Secret中設置保存Secret Token。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: px-storage-repl-1
provisioner: kubernetes.io/portworx-volume
parameters:
  repl: "1"
  openstorage.io/auth-secret-name: px-k8s-user
  openstorage.io/auth-secret-namespace: portworx
allowVolumeExpansion: true

如果您正在使用CSI,請確保設置其他的參數。

注意:這目前只在通過Portworx使用CSI時有效。

parameters:
  repl: "1"
  csi.storage.k8s.io/provisioner-secret-name: px-k8s-user
  csi.storage.k8s.io/provisioner-secret-namespace: portworx
  csi.storage.k8s.io/node-publish-secret-name: px-k8s-user
  csi.storage.k8s.io/node-publish-secret-namespace: portworx
  csi.storage.k8s.io/controller-expand-secret-name: px-k8s-user
  csi.storage.k8s.io/controller-expand-secret-namespace: portworx

完成此操作後,具備訪問存儲類權限的用戶可以創建卷。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
   name: mysql-data
spec:
   storageClass: px-storage-repl-1
   accessModes:
     - ReadWriteOnce
   resources:
     requests:
       storage: 12Gi

多租戶架構

當您創建上述PVC時,它將使用KubernetesToken作爲用戶進行身份驗證,從而確保該Kubernetes用戶是發出請求的用戶。這很好,但是多租戶環境下,他們都可以使用存儲類,因此我們需要一種方法來在不同的命名空間中使用多租戶的Token。這是因爲Kubernetes提供了使用命名空間隔離帳戶資源的好方法,但您需要更安全的多租戶解決方案。Portworx可以通過爲應用存儲卷添加訪問控制來達到多租戶安全管理。使用PX-Security進行多租戶管理,可以執行以下操作。

首先,爲租戶創建一個命名空間。

$ kubectl create namespace tenant-a-ns

使用以下創建一個名爲tenant-a.yaml 的文件:

name: tenant-a
email: [email protected]
sub: [email protected]/tenant
roles: ["system.user"]
groups: ["developers"]

使用tenant-name.yaml爲Kubernetes創建一個token:

TENANT_A_TOKEN=$(/opt/pwx/bin/pxctl auth token generate \
    --auth-config=tenant-a.yaml \
    --issuer=example-domain.com \
    --shared-secret=$PORTWORX_AUTH_SHARED_SECRET \
    --token-duration=1y)

將該租戶的Kubernetes Token保存在一個名爲/px-k8 -user的Secret中:

$ kubectl -n tenant-a-ns create secret \
  generic px-k8s-user \
  --from-literal=auth-token=$TENANT_A_TOKEN

現在可以設置Kubernetes存儲類,通過使用這個Secret,來獲得Token權限,並與Portworx開始通訊。

下面的CSI存儲類一旦創建,將使您的多租戶能夠使用存儲在其命名空間中的Secret中的Token,來創建卷,方法是在命名空間中查找Secret。在使用CSI時,存儲類將引用三種受支持操作的secret:provision, node-publish(mount/unmount), and controller-expand。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: px-storage
provisioner: pxd.portworx.com
parameters:
  repl: "1"
  csi.storage.k8s.io/provisioner-secret-name: px-k8s-user
  csi.storage.k8s.io/provisioner-secret-namespace: ${pvc.namespace}
  csi.storage.k8s.io/node-publish-secret-name: px-k8s-user
  csi.storage.k8s.io/node-publish-secret-namespace: ${pvc.namespace}
  csi.storage.k8s.io/controller-expand-secret-name: px-k8s-user
  csi.storage.k8s.io/controller-expand-secret-namespace: ${pvc.namespace}
allowVolumeExpansion: true

請注意 ${pvc.namespace}。這將確保CSI控制器獲得正確的Token,該Token與PVC的命名空間相關聯。您現在就有了一個基於Token身份驗證的多租戶解決方案。

我們在本Blog中有一部分沒有介紹的PX-Security功能就是Portworx卷的加密。您可以在這裏(how to work with Encrypted PVCs)查看更多的關於PVC加密的文檔 。您可以將Portworx RBAC與卷加密結合使用,來使Kubernetes中的數據更加安全。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章