PX-Security:针对Kubernetes持久卷的多租户受权、身份验证和RBAChtml
PX-Security演示视频连接
https://v.qq.com/x/page/s30609pfmuq.html
安全对于企业来讲相当重要,对于运行在Kubernetes上的基于微服务的应用来讲更是如此。
Kubernetes提供RBAC受权,根据不一样角色设定,管理Kubernetes内部特定资源的访问权限。这些机制对于管理Kubernetes的特定对象(如服务、命名空间、配额等)的访问权限很是有用。但命名空间和pod的安全策略自己,不足以限制谁有权限能够请求更改底层数据管理系统。node
许多企业经过CNI或CSI等API,调用其余的平台能力来提供网络和存储基础。Kubernetes所缺少的是将RBAC扩展到这些系统的能力,须要外部系统来确保受权和认证功能的实现。mysql
这就是为何Portworx与Kubernetes携手,经过对支撑Kubernetes中PVCs的持久卷,进行访问角色控制,来提供RBAC、加密和控制权限,这将建立一个无缝的保护层,为您的PVCs提供如下保护:golang
同一命名空间中的用户能够受到其角色的限制,好比他们能够具备读、写、管理员或其余定义的访问权限。sql
用户能够经过Token自动进行身份验证,这样审计请求的受权就能够针对特定命名空间来进行。json
能够将用户置于基于租户的命名空间中,从而为访问PVCs提供安全的多租户。api
即便用户看到存储类,也不意味着他们被受权建立PVC。安全
将Portworx RBAC与加密一块儿使用,意味着数据在host上是安全的,命名空间内的非受权用户不能访问数据。bash
要深刻了解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: storageadmin@example.com sub: storageadmin@example.com/storageadmin roles: ["system.admin"] groups: ["*"]
接下来,咱们将建立一个Kubernetes用户,该用户做为一个验证客户,Kubernetes容许该用户与Portworx交互,而且这些请求来自Kubernetes。您的存储管理员须要设置此用户。
使用如下内容建立一个名为kubernetes.yaml的文件:
name: Kubernetes email: kubernetes@local.net sub: kubernetes@local.net/kubernetes roles: ["system.user"] groups: ["kubernetes"]
最后,咱们将建立一个仅能看 (view-only) 权限的用户,用于演示Portworx如何限制对底层数据管理API的访问。
使用如下内容建立一个名为viewer.yaml的文件:
name: Viewer email: viewer@example.com sub: viewer@example.com/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: tenant@tenant-a.com sub: tenant@tenant-a.com/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保存在一个名为<tenant namespace>/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中的数据更加安全。