Modify node admission and node authorizer

This commit is contained in:
Xing Yang 2019-03-01 19:14:23 -08:00
parent 6265f4f78c
commit 85867e5625
10 changed files with 120 additions and 106 deletions

View File

@ -16,6 +16,7 @@ go_library(
"//pkg/apis/coordination:go_default_library", "//pkg/apis/coordination:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/policy:go_default_library", "//pkg/apis/policy:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library", "//pkg/auth/nodeidentifier:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis:go_default_library",
@ -30,7 +31,6 @@ go_library(
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
) )
@ -44,6 +44,7 @@ go_test(
"//pkg/apis/coordination:go_default_library", "//pkg/apis/coordination:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/policy:go_default_library", "//pkg/apis/policy:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library", "//pkg/auth/nodeidentifier:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis:go_default_library",
@ -57,7 +58,6 @@ go_test(
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )

View File

@ -32,13 +32,13 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
corev1lister "k8s.io/client-go/listers/core/v1" corev1lister "k8s.io/client-go/listers/core/v1"
csiv1alpha1 "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
"k8s.io/klog" "k8s.io/klog"
podutil "k8s.io/kubernetes/pkg/api/pod" podutil "k8s.io/kubernetes/pkg/api/pod"
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
coordapi "k8s.io/kubernetes/pkg/apis/coordination" coordapi "k8s.io/kubernetes/pkg/apis/coordination"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/policy"
storage "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/auth/nodeidentifier" "k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
@ -94,12 +94,12 @@ func (p *nodePlugin) ValidateInitialization() error {
} }
var ( var (
podResource = api.Resource("pods") podResource = api.Resource("pods")
nodeResource = api.Resource("nodes") nodeResource = api.Resource("nodes")
pvcResource = api.Resource("persistentvolumeclaims") pvcResource = api.Resource("persistentvolumeclaims")
svcacctResource = api.Resource("serviceaccounts") svcacctResource = api.Resource("serviceaccounts")
leaseResource = coordapi.Resource("leases") leaseResource = coordapi.Resource("leases")
csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos") csiNodeResource = storage.Resource("csinodes")
) )
func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
@ -151,9 +151,9 @@ func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces)
} }
return admission.NewForbidden(a, fmt.Errorf("disabled by feature gate %s", features.NodeLease)) return admission.NewForbidden(a, fmt.Errorf("disabled by feature gate %s", features.NodeLease))
case csiNodeInfoResource: case csiNodeResource:
if c.features.Enabled(features.KubeletPluginsWatcher) && c.features.Enabled(features.CSINodeInfo) { if c.features.Enabled(features.KubeletPluginsWatcher) && c.features.Enabled(features.CSINodeInfo) {
return c.admitCSINodeInfo(nodeName, a) return c.admitCSINode(nodeName, a)
} }
return admission.NewForbidden(a, fmt.Errorf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo)) return admission.NewForbidden(a, fmt.Errorf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo))
@ -530,8 +530,8 @@ func (r *nodePlugin) admitLease(nodeName string, a admission.Attributes) error {
return nil return nil
} }
func (c *nodePlugin) admitCSINodeInfo(nodeName string, a admission.Attributes) error { func (c *nodePlugin) admitCSINode(nodeName string, a admission.Attributes) error {
// the request must come from a node with the same name as the CSINodeInfo object // the request must come from a node with the same name as the CSINode object
if a.GetOperation() == admission.Create { if a.GetOperation() == admission.Create {
// a.GetName() won't return the name on create, so we drill down to the proposed object // a.GetName() won't return the name on create, so we drill down to the proposed object
accessor, err := meta.Accessor(a.GetObject()) accessor, err := meta.Accessor(a.GetObject())
@ -539,11 +539,11 @@ func (c *nodePlugin) admitCSINodeInfo(nodeName string, a admission.Attributes) e
return admission.NewForbidden(a, fmt.Errorf("unable to access the object name")) return admission.NewForbidden(a, fmt.Errorf("unable to access the object name"))
} }
if accessor.GetName() != nodeName { if accessor.GetName() != nodeName {
return admission.NewForbidden(a, fmt.Errorf("can only access CSINodeInfo with the same name as the requesting node")) return admission.NewForbidden(a, fmt.Errorf("can only access CSINode with the same name as the requesting node"))
} }
} else { } else {
if a.GetName() != nodeName { if a.GetName() != nodeName {
return admission.NewForbidden(a, fmt.Errorf("can only access CSINodeInfo with the same name as the requesting node")) return admission.NewForbidden(a, fmt.Errorf("can only access CSINode with the same name as the requesting node"))
} }
} }

View File

@ -33,11 +33,11 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
corev1lister "k8s.io/client-go/listers/core/v1" corev1lister "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
csiv1alpha1 "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
"k8s.io/kubernetes/pkg/apis/coordination" "k8s.io/kubernetes/pkg/apis/coordination"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/policy"
storage "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/auth/nodeidentifier" "k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
@ -306,14 +306,14 @@ func Test_nodePlugin_Admit(t *testing.T) {
}, },
} }
csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos").WithVersion("v1alpha1") csiNodeResource = storage.Resource("csinodes").WithVersion("v1beta1")
csiNodeInfoKind = schema.GroupVersionKind{Group: "csi.storage.k8s.io", Version: "v1alpha1", Kind: "CSINodeInfo"} csiNodeKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSINode"}
nodeInfo = &csiv1alpha1.CSINodeInfo{ nodeInfo = &storage.CSINode{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "mynode", Name: "mynode",
}, },
Spec: csiv1alpha1.CSINodeInfoSpec{ Spec: storage.CSINodeSpec{
Drivers: []csiv1alpha1.CSIDriverInfoSpec{ Drivers: []storage.CSINodeDriver{
{ {
Name: "com.example.csi/mydriver", Name: "com.example.csi/mydriver",
NodeID: "com.example.csi/mynode", NodeID: "com.example.csi/mynode",
@ -321,22 +321,13 @@ func Test_nodePlugin_Admit(t *testing.T) {
}, },
}, },
}, },
Status: csiv1alpha1.CSINodeInfoStatus{
Drivers: []csiv1alpha1.CSIDriverInfoStatus{
{
Name: "com.example.csi/mydriver",
Available: true,
VolumePluginMechanism: csiv1alpha1.VolumePluginMechanismInTree,
},
},
},
} }
nodeInfoWrongName = &csiv1alpha1.CSINodeInfo{ nodeInfoWrongName = &storage.CSINode{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "foo", Name: "foo",
}, },
Spec: csiv1alpha1.CSINodeInfoSpec{ Spec: storage.CSINodeSpec{
Drivers: []csiv1alpha1.CSIDriverInfoSpec{ Drivers: []storage.CSINodeDriver{
{ {
Name: "com.example.csi/mydriver", Name: "com.example.csi/mydriver",
NodeID: "com.example.csi/foo", NodeID: "com.example.csi/foo",
@ -344,15 +335,6 @@ func Test_nodePlugin_Admit(t *testing.T) {
}, },
}, },
}, },
Status: csiv1alpha1.CSINodeInfoStatus{
Drivers: []csiv1alpha1.CSIDriverInfoStatus{
{
Name: "com.example.csi/mydriver",
Available: true,
VolumePluginMechanism: csiv1alpha1.VolumePluginMechanismInTree,
},
},
},
} }
noExistingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil) noExistingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
@ -1183,46 +1165,46 @@ func Test_nodePlugin_Admit(t *testing.T) {
features: leaseEnabledFeature, features: leaseEnabledFeature,
err: "", err: "",
}, },
// CSINodeInfo // CSINode
{ {
name: "disallowed create CSINodeInfo - feature disabled", name: "disallowed create CSINode - feature disabled",
attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Create, false, mynode), attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, false, mynode),
features: csiNodeInfoDisabledFeature, features: csiNodeInfoDisabledFeature,
err: fmt.Sprintf("forbidden: disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo), err: fmt.Sprintf("forbidden: disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo),
}, },
{ {
name: "disallowed create another node's CSINodeInfo - feature enabled", name: "disallowed create another node's CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfoWrongName, nil, csiNodeInfoKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeInfoResource, "", admission.Create, false, mynode), attributes: admission.NewAttributesRecord(nodeInfoWrongName, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Create, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "forbidden: ", err: "forbidden: ",
}, },
{ {
name: "disallowed update another node's CSINodeInfo - feature enabled", name: "disallowed update another node's CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfoWrongName, nodeInfoWrongName, csiNodeInfoKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeInfoResource, "", admission.Update, false, mynode), attributes: admission.NewAttributesRecord(nodeInfoWrongName, nodeInfoWrongName, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Update, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "forbidden: ", err: "forbidden: ",
}, },
{ {
name: "disallowed delete another node's CSINodeInfo - feature enabled", name: "disallowed delete another node's CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nil, nil, csiNodeInfoKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeInfoResource, "", admission.Delete, false, mynode), attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Delete, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "forbidden: ", err: "forbidden: ",
}, },
{ {
name: "allowed create node CSINodeInfo - feature enabled", name: "allowed create node CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Create, false, mynode), attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "", err: "",
}, },
{ {
name: "allowed update node CSINodeInfo - feature enabled", name: "allowed update node CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfo, nodeInfo, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Update, false, mynode), attributes: admission.NewAttributesRecord(nodeInfo, nodeInfo, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Update, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "", err: "",
}, },
{ {
name: "allowed delete node CSINodeInfo - feature enabled", name: "allowed delete node CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nil, nil, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Delete, false, mynode), attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Delete, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "", err: "",
}, },

View File

@ -56,7 +56,6 @@ go_library(
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/informers/storage/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/storage/v1:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//third_party/forked/gonum/graph:go_default_library", "//third_party/forked/gonum/graph:go_default_library",
"//third_party/forked/gonum/graph/simple:go_default_library", "//third_party/forked/gonum/graph/simple:go_default_library",
"//third_party/forked/gonum/graph/traverse:go_default_library", "//third_party/forked/gonum/graph/traverse:go_default_library",

View File

@ -25,7 +25,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
csiv1alpha1 "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
coordapi "k8s.io/kubernetes/pkg/apis/coordination" coordapi "k8s.io/kubernetes/pkg/apis/coordination"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
storageapi "k8s.io/kubernetes/pkg/apis/storage" storageapi "k8s.io/kubernetes/pkg/apis/storage"
@ -68,14 +67,14 @@ func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules
} }
var ( var (
configMapResource = api.Resource("configmaps") configMapResource = api.Resource("configmaps")
secretResource = api.Resource("secrets") secretResource = api.Resource("secrets")
pvcResource = api.Resource("persistentvolumeclaims") pvcResource = api.Resource("persistentvolumeclaims")
pvResource = api.Resource("persistentvolumes") pvResource = api.Resource("persistentvolumes")
vaResource = storageapi.Resource("volumeattachments") vaResource = storageapi.Resource("volumeattachments")
svcAcctResource = api.Resource("serviceaccounts") svcAcctResource = api.Resource("serviceaccounts")
leaseResource = coordapi.Resource("leases") leaseResource = coordapi.Resource("leases")
csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos") csiNodeResource = storageapi.Resource("csinodes")
) )
func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) { func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) {
@ -122,9 +121,9 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
return r.authorizeLease(nodeName, attrs) return r.authorizeLease(nodeName, attrs)
} }
return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gate %s", features.NodeLease), nil return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gate %s", features.NodeLease), nil
case csiNodeInfoResource: case csiNodeResource:
if r.features.Enabled(features.KubeletPluginsWatcher) && r.features.Enabled(features.CSINodeInfo) { if r.features.Enabled(features.KubeletPluginsWatcher) && r.features.Enabled(features.CSINodeInfo) {
return r.authorizeCSINodeInfo(nodeName, attrs) return r.authorizeCSINode(nodeName, attrs)
} }
return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo), nil return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo), nil
} }
@ -260,8 +259,8 @@ func (r *NodeAuthorizer) authorizeLease(nodeName string, attrs authorizer.Attrib
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }
// authorizeCSINodeInfo authorizes node requests to CSINodeInfo csi.storage.k8s.io/csinodeinfos // authorizeCSINode authorizes node requests to CSINode storage.k8s.io/csinodes
func (r *NodeAuthorizer) authorizeCSINodeInfo(nodeName string, attrs authorizer.Attributes) (authorizer.Decision, string, error) { func (r *NodeAuthorizer) authorizeCSINode(nodeName string, attrs authorizer.Attributes) (authorizer.Decision, string, error) {
// allowed verbs: get, create, update, patch, delete // allowed verbs: get, create, update, patch, delete
verb := attrs.GetVerb() verb := attrs.GetVerb()
if verb != "get" && if verb != "get" &&
@ -270,20 +269,20 @@ func (r *NodeAuthorizer) authorizeCSINodeInfo(nodeName string, attrs authorizer.
verb != "patch" && verb != "patch" &&
verb != "delete" { verb != "delete" {
klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
return authorizer.DecisionNoOpinion, "can only get, create, update, patch, or delete a CSINodeInfo", nil return authorizer.DecisionNoOpinion, "can only get, create, update, patch, or delete a CSINode", nil
} }
if len(attrs.GetSubresource()) > 0 { if len(attrs.GetSubresource()) > 0 {
klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
return authorizer.DecisionNoOpinion, "cannot authorize CSINodeInfo subresources", nil return authorizer.DecisionNoOpinion, "cannot authorize CSINode subresources", nil
} }
// the request must come from a node with the same name as the CSINodeInfo // the request must come from a node with the same name as the CSINode
// note we skip this check for create, since the authorizer doesn't know the name on create // note we skip this check for create, since the authorizer doesn't know the name on create
// the noderestriction admission plugin is capable of performing this check at create time // the noderestriction admission plugin is capable of performing this check at create time
if verb != "create" && attrs.GetName() != nodeName { if verb != "create" && attrs.GetName() != nodeName {
klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
return authorizer.DecisionNoOpinion, "can only access CSINodeInfo with the same name as the requesting node", nil return authorizer.DecisionNoOpinion, "can only access CSINode with the same name as the requesting node", nil
} }
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil

View File

@ -352,82 +352,82 @@ func TestAuthorizer(t *testing.T) {
features: leaseEnabledFeature, features: leaseEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
// CSINodeInfo // CSINode
{ {
name: "disallowed CSINodeInfo - feature disabled", name: "disallowed CSINode - feature disabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoDisabledFeature, features: csiNodeInfoDisabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed CSINodeInfo with subresource - feature enabled", name: "disallowed CSINode with subresource - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", Subresource: "csiDrivers", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", Subresource: "csiDrivers", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed get another node's CSINodeInfo - feature enabled", name: "disallowed get another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed update another node's CSINodeInfo - feature enabled", name: "disallowed update another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed patch another node's CSINodeInfo - feature enabled", name: "disallowed patch another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed delete another node's CSINodeInfo - feature enabled", name: "disallowed delete another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed list CSINodeInfos - feature enabled", name: "disallowed list CSINodes - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "list", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "list", Resource: "csinodes", APIGroup: "storage.k8s.io"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed watch CSINodeInfos - feature enabled", name: "disallowed watch CSINodes - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "watch", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "watch", Resource: "csinodes", APIGroup: "storage.k8s.io"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "allowed get CSINodeInfo - feature enabled", name: "allowed get CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed create CSINodeInfo - feature enabled", name: "allowed create CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed update CSINodeInfo - feature enabled", name: "allowed update CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed patch CSINodeInfo - feature enabled", name: "allowed patch CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed delete CSINodeInfo - feature enabled", name: "allowed delete CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },

View File

@ -74,7 +74,7 @@ func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding)
if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()) role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie())
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "watch", "list").Groups("csi.storage.k8s.io").Resources("csidrivers").RuleOrDie()) role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csidrivers").RuleOrDie())
} }
} }

View File

@ -160,13 +160,13 @@ func NodeRules() []rbacv1.PolicyRule {
volAttachRule := rbacv1helpers.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie() volAttachRule := rbacv1helpers.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()
nodePolicyRules = append(nodePolicyRules, volAttachRule) nodePolicyRules = append(nodePolicyRules, volAttachRule)
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
csiDriverRule := rbacv1helpers.NewRule("get", "watch", "list").Groups("csi.storage.k8s.io").Resources("csidrivers").RuleOrDie() csiDriverRule := rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csidrivers").RuleOrDie()
nodePolicyRules = append(nodePolicyRules, csiDriverRule) nodePolicyRules = append(nodePolicyRules, csiDriverRule)
} }
} }
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher) && if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher) &&
utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) { utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
csiNodeInfoRule := rbacv1helpers.NewRule("get", "create", "update", "patch", "delete").Groups("csi.storage.k8s.io").Resources("csinodeinfos").RuleOrDie() csiNodeInfoRule := rbacv1helpers.NewRule("get", "create", "update", "patch", "delete").Groups("storage.k8s.io").Resources("csinodes").RuleOrDie()
nodePolicyRules = append(nodePolicyRules, csiNodeInfoRule) nodePolicyRules = append(nodePolicyRules, csiNodeInfoRule)
} }
@ -514,7 +514,7 @@ func ClusterRoles() []rbacv1.ClusterRole {
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
} }
if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) { if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
externalProvisionerRules = append(externalProvisionerRules, rbacv1helpers.NewRule("get", "watch", "list").Groups("csi.storage.k8s.io").Resources("csinodeinfos").RuleOrDie()) externalProvisionerRules = append(externalProvisionerRules, rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csinodes").RuleOrDie())
} }
roles = append(roles, rbacv1.ClusterRole{ roles = append(roles, rbacv1.ClusterRole{
// a role for the csi external provisioner // a role for the csi external provisioner

View File

@ -532,6 +532,14 @@ items:
- get - get
- list - list
- watch - watch
- apiGroups:
- storage.k8s.io
resources:
- csinodes
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1 - apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
@ -985,6 +993,24 @@ items:
- volumeattachments - volumeattachments
verbs: verbs:
- get - get
- apiGroups:
- storage.k8s.io
resources:
- csidrivers
verbs:
- get
- list
- watch
- apiGroups:
- storage.k8s.io
resources:
- csinodes
verbs:
- create
- delete
- get
- patch
- update
- apiGroups: - apiGroups:
- coordination.k8s.io - coordination.k8s.io
resources: resources:

View File

@ -58,6 +58,14 @@ items:
- get - get
- list - list
- watch - watch
- apiGroups:
- storage.k8s.io
resources:
- csidrivers
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1 - apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: ClusterRole
metadata: metadata: