-
Notifications
You must be signed in to change notification settings - Fork 39.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding credentials support for k8s core CSI #60118
Adding credentials support for k8s core CSI #60118
Conversation
/sig storage |
@vladimirvivien @saad-ali Please review. |
@saad-ali addressed changes in the proposal, PTAL. |
pkg/apis/core/types.go
Outdated
// 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Update comment
// ControllerPublishSecretRef is a reference to the secret object containing
// sensitive information to pass to the CSI driver to complete the CSI
// ControllerPublishVolume and ControllerUnpublishVolume calls.
// This field is optional, and may be empty if no secret is required. If the
// secret object contains more than one secret, all secrets are passed.
// +optional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/apis/core/types.go
Outdated
// NodeStageSecretRef is a reference to the secret object containing sensitive | ||
// information to pass to the CSI driver to complete the CSI NodeStageVolume | ||
// and NodeStageVolume and NodeUnstageVolume calls. | ||
// This secret will be fetched by the kubelet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this line.
pkg/apis/core/types.go
Outdated
// NodePublishSecretRef is a reference to the secret object containing | ||
// sensitive information to pass to the CSI driver to complete the CSI | ||
// NodePublishVolume and NodeUnpublishVolume calls. | ||
// This secret will be fetched by the kubelet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove this line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/volume/csi/csi_util.go
Outdated
|
||
func getCredentialsFromSecret(k8s kubernetes.Interface, sn, ns string) map[string]string { | ||
credentials := map[string]string{} | ||
if len(sn) == 0 || len(ns) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think empty namespace maybe a valid case (default namespace?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, in reality it will not be ever empty as I take it from pod's spec. Removed ns check.
@@ -195,7 +195,12 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { | |||
if len(fsType) == 0 { | |||
fsType = defaultFSType | |||
} | |||
|
|||
nodePublishCredentials := map[string]string{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not your code, but, can you add a commit to remove probe related code in this PR too:
...
if err := csi.NodeProbe(ctx, csiVersion); err != nil {
...
and all related comments, e.g.:
// TODO (vladimirvivien) use this method to probe controller using CSI.NodeProbe() call
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/volume/csi/csi_mounter.go
Outdated
|
||
nodePublishCredentials := map[string]string{} | ||
if c.spec.PersistentVolume.Spec.CSI.NodePublishSecretRef != nil { | ||
sn := c.spec.PersistentVolume.Spec.CSI.NodePublishSecretRef.Name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use csiSource.NodePublishSecretRef.Name
everywhere instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/volume/csi/csi_mounter.go
Outdated
@@ -195,7 +195,12 @@ func (c *csiMountMgr) SetUpAt(dir string, fsGroup *int64) error { | |||
if len(fsType) == 0 { | |||
fsType = defaultFSType | |||
} | |||
|
|||
nodePublishCredentials := map[string]string{} | |||
if c.spec.PersistentVolume.Spec.CSI.NodePublishSecretRef != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure, but I think an empty namespace is valid. So maybe just check if NodePublishSecretRef.Name != nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I check for the presence of Secret Object, Name is string, it could be not nil but "". If you do not mind I would like to keep this check for object not nil and secret name validation in getCredentialsFromSecret
@saad-ali addressed your comments, PTAL. |
I forgot one more set of changes: The Kubernetes API server's node authorizer must be updated to allow kubelet to access the secrets referenced by |
verify gofmt is failing, please run gofmt |
Close, though the node authorizer today allows the kubelet to read any secret referenced by a PV. As of this PR, only some secret references should be kubelet-visible (specifically, ControllerPublishSecretRef should not be). You can make that a parameter to the visitor ( |
pkg/api/persistentvolume/util.go
Outdated
@@ -111,6 +111,32 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool { | |||
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Namespace, source.StorageOS.SecretRef.Name) { | |||
return false | |||
} | |||
case source.CSI != nil: | |||
if source.CSI.ControllerPublishSecretRef != nil { | |||
if len(source.CSI.ControllerPublishSecretRef.Name) == 0 || len(source.CSI.ControllerPublishSecretRef.Namespace) == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api validation should be added to prevent these from being empty... no need to recheck here (or in the other blocks)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@liggitt could you please point me where the validation you mentioned should be added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kubernetes/pkg/apis/core/validation/validation.go
Lines 1432 to 1456 in 82eeda0
func validateCSIPersistentVolumeSource(csi *core.CSIPersistentVolumeSource, fldPath *field.Path) field.ErrorList { | |
allErrs := field.ErrorList{} | |
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { | |
allErrs = append(allErrs, field.Forbidden(fldPath, "CSIPersistentVolume disabled by feature-gate")) | |
} | |
if len(csi.Driver) == 0 { | |
allErrs = append(allErrs, field.Required(fldPath.Child("driver"), "")) | |
} | |
if len(csi.Driver) > 63 { | |
allErrs = append(allErrs, field.TooLong(fldPath.Child("driver"), csi.Driver, 63)) | |
} | |
if !csiDriverNameRexp.MatchString(csi.Driver) { | |
allErrs = append(allErrs, field.Invalid(fldPath.Child("driver"), csi.Driver, validation.RegexError(csiDriverNameRexpErrMsg, csiDriverNameRexpFmt, "csi-hostpath"))) | |
} | |
if len(csi.VolumeHandle) == 0 { | |
allErrs = append(allErrs, field.Required(fldPath.Child("volumeHandle"), "")) | |
} | |
return allErrs | |
} |
/test pull-kubernetes-unit |
@@ -1452,6 +1452,33 @@ func validateCSIPersistentVolumeSource(csi *core.CSIPersistentVolumeSource, fldP | |||
allErrs = append(allErrs, field.Required(fldPath.Child("volumeHandle"), "")) | |||
} | |||
|
|||
if csi.ControllerPublishSecretRef != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for all of these, ensure name is a valid secret name and namespace is a valid namespace name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/volume/csi/csi_mounter.go
Outdated
nodePublishCredentials := map[string]string{} | ||
if csiSource.NodePublishSecretRef != nil { | ||
sn := csiSource.NodePublishSecretRef.Name | ||
ns := c.pod.ObjectMeta.Namespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be csiSource.NodePublishSecretRef.Namespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to protect against this type of mistake, consider passing the secret ref to getCredentialsFromSecret instead of loose name/namespace fields
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
pkg/volume/csi/csi_mounter.go
Outdated
nodeUnpublishCredentials := map[string]string{} | ||
if csiSource.NodePublishSecretRef != nil { | ||
sn := csiSource.NodePublishSecretRef.Name | ||
ns := c.pod.ObjectMeta.Namespace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NodePublishSecretRef.Namespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be passing SecreteReference to getCredentialsFromSecret.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM mod nit
@liggitt for node authorizer review
pkg/api/persistentvolume/util.go
Outdated
@@ -40,11 +40,11 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool { | |||
switch { | |||
case source.AzureFile != nil: | |||
if source.AzureFile.SecretNamespace != nil && len(*source.AzureFile.SecretNamespace) > 0 { | |||
if len(source.AzureFile.SecretName) > 0 && !visitor(*source.AzureFile.SecretNamespace, source.AzureFile.SecretName) { | |||
if len(source.AzureFile.SecretName) > 0 && !visitor(*source.AzureFile.SecretNamespace, source.AzureFile.SecretName, true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: when it is unclear what the value means, it's nice to have a comment, for example:
!visitor(
*source.AzureFile.SecretNamespace,
source.AzureFile.SecretName,
true /* kubeletVisible */) {
But it's a personal preference, up to you if you want to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, it is more next developer friendly :)
credentials := map[string]string{} | ||
secret, err := k8s.CoreV1().Secrets(secretRef.Namespace).Get(secretRef.Name, meta.GetOptions{}) | ||
if err != nil { | ||
glog.Warningf("failed to find the secret %s in the namespace %s with error: %v\n", secretRef.Name, secretRef.Namespace, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expected this to return the error and avoid making the CSI call
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, credentials are not mandatory, so if not specified I do not think we should fail CSI call. @saad-ali what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if they were specified by the PV, then it seems like an error resolving them should be considered an error in input gathering and short-circuit
|
||
nodePublishCredentials := map[string]string{} | ||
if csiSource.NodePublishSecretRef != nil { | ||
nodePublishCredentials = getCredentialsFromSecret(c.k8s, csiSource.NodePublishSecretRef) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here and below, I expected to handle an error return from getCredentialsFromSecret by short-circuiting and returning the error, rather than making the csi call with an empty credentials map
API and node authorizer bits LGTM |
/approve |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
/approve
For vendored dep update: |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: brendandburns, liggitt, saad-ali, sbezverk The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/test all [submit-queue is verifying that this PR is safe to merge] |
/test pull-kubernetes-unit |
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here. |
PR implements changes proposed in: kubernetes/community#1816