mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
Modify node admission and node authorizer
This commit is contained in:
parent
6265f4f78c
commit
85867e5625
@ -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",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -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"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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: "",
|
||||||
},
|
},
|
||||||
|
@ -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",
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user