Skip to content

Commit

Permalink
Introduce CSI credential handling
Browse files Browse the repository at this point in the history
  • Loading branch information
saad-ali committed Feb 20, 2018
1 parent 94a104d commit ac7d271
Showing 1 changed file with 100 additions and 12 deletions.
112 changes: 100 additions & 12 deletions contributors/design-proposals/storage/container-storage-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,34 +444,122 @@ Alternatively, deployment could be simplified by having all components (includin
This part of proposal is not going to be implemented in alpha release.

#### End user credentials
CSI allows specifying *end user credentials* in all operations. Kubernetes does not have facility to configure a Secret per *user*, we usually track objects per *namespace*. Therefore we decided to postpone implementation of these credentials and wait until CSI is clarified.
CSI allows specifying credentials in CreateVolume/DeleteVolume, ControllerPublishVolume/ControllerUnpublishVolume, and NodePublishVolume/NodeUnpublishVolume operations.

Kubernetes will enable cluster admins and application developers to specify these credentials by referencing Kubernetes secret object(s). Kubernetes (either the core components or helper containers) will fetch the secret(s) and pass them to the CSI volume plugin.

#### CreateVolume/DeleteVolume Credentials

```yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: fast-storage
provisioner: com.example.team.csi-driver
parameters:
type: pd-ssd
csiProvisionerSecretName: mysecret
csiProvisionerSecretNamespace: mynamespaace
```
The CSI external-provisioner will reserve the parameter keys `csiProvisionerSecretName` and `csiProvisionerSecretNamespace`. If specified, the CSI Provisioner will fetch the secret `csiProvisionerSecretName` in the Kubernetes namespace `csiProvisionerSecretNamespace` and pass it to:
1. The CSI `CreateVolumeRequest` in the `controller_create_credentials` field.
2. The CSI `DeleteVolumeRequest` in the `controller_delete_credentials` field.

It is assumed that since StorageClass is a non-namespaced field, only trusted users (e.g. cluster administrators) should be able to create a StorageClass and, thus, specify which secret to fetch.

Permissions for the corresponding external-provisioner may be limited to the specified namespace to prevent a compromised provisioner from gaining any other secrets.

If the secret object contains more than one secret, all secrets are passed.

#### Volume specific credentials
Some storage technologies (e.g. iSCSI with CHAP) require credentials tied to the volume (iSCSI LUN) that must be used during `NodePublish` request. It is expected that these credentials will be provided during dynamic provisioning of the volume, however CSI `CreateVolume` response does not provide any. In case it gets fixed soon external provisioner can save the secrets in a dedicated namespace and make them available to external attacher and internal CSI volume plugin using these `CSIPersistentVolumeSource` fields:
#### ControllerPublishVolume/ControllerUnpublishVolume Credentials

// ...
```go
type CSIPersistentVolumeSource struct {
// Optional: MountSecretRef is a reference to the secret object containing
// sensitive information to pass to the CSI driver during NodePublish.
// Optional: ControllerPublishSecretRef is a reference to the secret object
// containing sensitive information to pass to the CSI driver during
// ControllerPublishVolume and ControllerUnpublishVolume calls.
// This may be empty if no secret is required. If the secret object contains
// more than one secret, all secrets are passed.
// +optional
MountSecretRef *SecretReference `json:"mountSecretRef,omitempty" protobuf:"bytes,3,opt,name=mountSecretRef"`
ControllerPublishSecretRef *SecretReference `json:"controllerPublishSecretRef,omitempty" protobuf:"bytes,4,opt,name=controllerPublishSecretRef"`
}
```

If specified, the CSI external-attacher will fetch the Kubernetes secret referenced by `ControllerPublishSecretRef` and pass it to:
1. The CSI `ControllerPublishVolume` in the `controller_publish_credentials` field.
2. The CSI `ControllerUnpublishVolume` in the `controller_unpublish_credentials` field.

For the beta implementation of this feature instead of a new filed in the `CSIPersistentVolumeSource`, the secret reference will be passed via an annotation in the PV object:

```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
annotations:
"volume.beta.kubernetes.io/controller-publish-secret-name": "mysecret"
"volume.beta.kubernetes.io/controller-publish-secret-namespace": "mysecretnamespace"
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
csi:
driver: com.example.team.csi-driver
volumeHandle: volumeName
readOnly: false

```

It is assumed that since `PersistentVolume` objects are non-namespaced and `CSIPersistentVolumeSource` can only be referenced via a `PersistentVolume`, only trusted users (e.g. cluster administrators) should be able to create a `PersistentVolume` objects and, thus, specify which secret to fetch.

Permissions for the corresponding external-attacher may be limited to the specified namespace to prevent a compromised attacher from gaining any other secrets.

// Optional: AttachSecretRef is a reference to the secret object containing
// sensitive information to pass to the CSI driver during ControllerPublish.
#### NodePublishVolume/NodeUnpublishVolume Credentials

```go
type PersistentVolumeClaimSpec struct {

// Optional: NodePublishSecretRef is a reference to the secret object
// containing sensitive information to pass to the CSI driver during
// NodePublishVolume and NodeUnpublishVolume calls.
// The namespace of the secret is assumed to be the same as the namespace as
// the pod referencing this PVC.
// This may be empty if no secret is required. If the secret object contains
// more than one secret, all secrets are passed.
// +optional
AttachSecretRef *SecretReference `json:"attachSecretRef,omitempty" protobuf:"bytes,4,opt,name=attachSecretRef"`
NodePublishSecretRef *LocalObjectReference `json:"nodePublishSecretRef,omitempty" protobuf:"bytes,3,opt,name=nodePublishSecretRef"`

}
```

Note that a malicious provisioner could obtain an arbitrary secret by setting the mount secret in PV object to whatever secret it wants. It is assumed that cluster admins will only run trusted provisioners.
If specified, the kubelet will fetch the Kubernetes secret referenced by `ControllerPublishSecretRef` and pass it to:
1. The CSI `NodePublishVolume` in the `node_publish_credentials` field.
2. The CSI `NodeUnpublishVolume` in the `node_unpublish_credentials` field.

For the beta implementation of this feature instead of a new filed in the `PersistentVolumeClaimSpec`, the secret reference will be passed via an annotation in the PV object:

```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-request-for-storage
annotations:
"volume.beta.kubernetes.io/node-publish-secret-name": "mysecret"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: fast-storage
```
The purpose of this credential is to ensure that the end user requesting storage has permission to use the specified volume. Therefore the namespace of the secret may not be specified and is assumed to be the same as the namespace of the pod referencing the PVC.
Because the kubelet would be responsible for fetching and passing the mount secret to the CSI driver,the Kubernetes NodeAuthorizer must be updated to allow kubelet read access to mount secrets.
Kubelet is allowed to fetch secrets in the namespace of the pod that it is setting up.
## Alternatives Considered
Expand Down

0 comments on commit ac7d271

Please sign in to comment.