Encrypting Kubernetes PVCs on FlashArray with Vault
Portworx Encrypted Volumes
Portworx has two different kinds of encrypted volumes:
-
Encrypted Volumes
Encrypted volumes are regular volumes which can be accessed from only one node.
-
Encrypted Sharedv4 Volumes
Encrypted sharedv4 volume allows access to the same encrypted volume from multiple nodes.
There are two ways in which Portworx volumes can be encrypted and are dependent on how the Vault secret key is provided to Portworx.
Encryption using Storage Class
In this method, Portworx uses the cluster wide secret key to encrypt PVCs.
- By default, Portworx looks for the secret in path
secret/<secret-name>
and gets the first value under the path. Users can modify the path with BACKEND_PATH or BASE_PATH, depending on the vault's version. - The cluster wide secret is the global secret-name for the cluster.
- secret-name can be modified with annotations. See the next section for an example.
From the diagram:
- The top-most secret can be accessed with default BACKEND_PATH
secret/
and secret-namepx-vault
. - The middle secret can be accessed with default BACKEND_PATH
secret/
and secret-namecustom/name
. - The bottom secret can be accessed with BACKEND_PATH
aws-secret/
and secret-nameaws-vault
.
Step 1: Store the secret in Vault
vault kv put secret/px-vault foo=bar
Step 2: Set a cluster wide secret
A cluster wide secret key is a common key that can be used to encrypt all your volumes. This common key needs to be pre-created in your KMS provider. You can set the cluster secret key using the following command:
pxctl secrets set-cluster-key
Enter cluster wide secret key: *****
Successfully set cluster secret key!
In the above prompt you need to enter the secret key that you created in your KMS. This command needs to be run just once for the cluster.
To use the secret we just created, enter px-vault
for the the cluster wide sceret.
If you are using Vault Namespaces use the following command to set the cluster-wide secret key in a specific vault namespace:
pxctl secrets set-cluster-key --secret_options=vault-namespace=<name of vault-namespace>
Step 3: Create a StorageClass
Create a storage class with the secure
parameter set to true
.
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: px-secure-sc
provisioner: pxd.portworx.com
parameters:
secure: "true"
repl: "3"
To create a sharedv4 encrypted volume set the sharedv4
parameter to true
as well.
Step 4: Create Persistent Volume Claim
Create a PVC that uses the above px-secure-sc
storage class.
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: secure-pvc
spec:
storageClassName: px-secure-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
Step 5: Verify the volume
Once the PVC has been created, verify the volume created in Portworx is encrypted:
PX_POD=$(kubectl get pods -l name=portworx -n <px-namespace> -o jsonpath='{.items[0].metadata.name}')
kubectl exec $PX_POD -n <px-namespace> -- /opt/pwx/bin/pxctl volume list
ID NAME ... ENCRYPTED ...
10852605918962284 pvc-xxxxxxxx-xxxx-xxxx-xxxx-080027ee1df7 ... yes ...
Encryption using PVC annotations
In this method, each PVC can be encrypted with its own secret key.
Step 1: Create a Storage Class
Create a storage class with the secure
parameter set to true
.
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: px-secure-sc
provisioner: pxd.portworx.com
parameters:
secure: "true"
repl: "3"
To create a sharedv4 encrypted volume set the sharedv4
parameter to true
as well.