Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
ecfd18e2
Unverified
Commit
ecfd18e2
authored
Jan 16, 2018
by
Jordan Liggitt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add get volumeattachments support to Node authorizer
parent
ba09fade
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
244 additions
and
35 deletions
+244
-35
config.go
pkg/kubeapiserver/authorizer/config.go
+1
-0
BUILD
plugin/pkg/auth/authorizer/node/BUILD
+6
-0
graph.go
plugin/pkg/auth/authorizer/node/graph.go
+25
-0
graph_populator.go
plugin/pkg/auth/authorizer/node/graph_populator.go
+46
-1
node_authorizer.go
plugin/pkg/auth/authorizer/node/node_authorizer.go
+12
-1
node_authorizer_test.go
plugin/pkg/auth/authorizer/node/node_authorizer_test.go
+100
-19
BUILD
test/integration/auth/BUILD
+2
-0
node_test.go
test/integration/auth/node_test.go
+48
-13
master_utils.go
test/integration/framework/master_utils.go
+4
-1
No files found.
pkg/kubeapiserver/authorizer/config.go
View file @
ecfd18e2
...
@@ -82,6 +82,7 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR
...
@@ -82,6 +82,7 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR
graph
,
graph
,
config
.
InformerFactory
.
Core
()
.
InternalVersion
()
.
Pods
(),
config
.
InformerFactory
.
Core
()
.
InternalVersion
()
.
Pods
(),
config
.
InformerFactory
.
Core
()
.
InternalVersion
()
.
PersistentVolumes
(),
config
.
InformerFactory
.
Core
()
.
InternalVersion
()
.
PersistentVolumes
(),
config
.
VersionedInformerFactory
.
Storage
()
.
V1alpha1
()
.
VolumeAttachments
(),
)
)
nodeAuthorizer
:=
node
.
NewAuthorizer
(
graph
,
nodeidentifier
.
NewDefaultNodeIdentifier
(),
bootstrappolicy
.
NodeRules
())
nodeAuthorizer
:=
node
.
NewAuthorizer
(
graph
,
nodeidentifier
.
NewDefaultNodeIdentifier
(),
bootstrappolicy
.
NodeRules
())
authorizers
=
append
(
authorizers
,
nodeAuthorizer
)
authorizers
=
append
(
authorizers
,
nodeAuthorizer
)
...
...
plugin/pkg/auth/authorizer/node/BUILD
View file @
ecfd18e2
...
@@ -14,10 +14,13 @@ go_test(
...
@@ -14,10 +14,13 @@ go_test(
deps = [
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/features:go_default_library",
"//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
"//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
"//vendor/k8s.io/api/storage/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
],
)
)
...
@@ -34,6 +37,7 @@ go_library(
...
@@ -34,6 +37,7 @@ go_library(
"//pkg/api/pod:go_default_library",
"//pkg/api/pod:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library",
"//pkg/client/informers/informers_generated/internalversion/core/internalversion:go_default_library",
"//pkg/client/informers/informers_generated/internalversion/core/internalversion:go_default_library",
"//pkg/features:go_default_library",
"//pkg/features:go_default_library",
...
@@ -42,9 +46,11 @@ go_library(
...
@@ -42,9 +46,11 @@ go_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",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/storage/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/client-go/informers/storage/v1alpha1:go_default_library",
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
],
],
)
)
...
...
plugin/pkg/auth/authorizer/node/graph.go
View file @
ecfd18e2
...
@@ -106,6 +106,7 @@ const (
...
@@ -106,6 +106,7 @@ const (
pvcVertexType
pvcVertexType
pvVertexType
pvVertexType
secretVertexType
secretVertexType
vaVertexType
)
)
var
vertexTypes
=
map
[
vertexType
]
string
{
var
vertexTypes
=
map
[
vertexType
]
string
{
...
@@ -115,6 +116,7 @@ var vertexTypes = map[vertexType]string{
...
@@ -115,6 +116,7 @@ var vertexTypes = map[vertexType]string{
pvcVertexType
:
"pvc"
,
pvcVertexType
:
"pvc"
,
pvVertexType
:
"pv"
,
pvVertexType
:
"pv"
,
secretVertexType
:
"secret"
,
secretVertexType
:
"secret"
,
vaVertexType
:
"volumeattachment"
,
}
}
// must be called under a write lock
// must be called under a write lock
...
@@ -263,3 +265,26 @@ func (g *Graph) DeletePV(name string) {
...
@@ -263,3 +265,26 @@ func (g *Graph) DeletePV(name string) {
defer
g
.
lock
.
Unlock
()
defer
g
.
lock
.
Unlock
()
g
.
deleteVertex_locked
(
pvVertexType
,
""
,
name
)
g
.
deleteVertex_locked
(
pvVertexType
,
""
,
name
)
}
}
// AddVolumeAttachment sets up edges for the following relationships:
//
// volume attachment -> node
func
(
g
*
Graph
)
AddVolumeAttachment
(
attachmentName
,
nodeName
string
)
{
g
.
lock
.
Lock
()
defer
g
.
lock
.
Unlock
()
// clear existing edges
g
.
deleteVertex_locked
(
vaVertexType
,
""
,
attachmentName
)
// if we have a node, establish new edges
if
len
(
nodeName
)
>
0
{
vaVertex
:=
g
.
getOrCreateVertex_locked
(
vaVertexType
,
""
,
attachmentName
)
nodeVertex
:=
g
.
getOrCreateVertex_locked
(
nodeVertexType
,
""
,
nodeName
)
g
.
graph
.
SetEdge
(
newDestinationEdge
(
vaVertex
,
nodeVertex
,
nodeVertex
))
}
}
func
(
g
*
Graph
)
DeleteVolumeAttachment
(
name
string
)
{
g
.
lock
.
Lock
()
defer
g
.
lock
.
Unlock
()
g
.
deleteVertex_locked
(
vaVertexType
,
""
,
name
)
}
plugin/pkg/auth/authorizer/node/graph_populator.go
View file @
ecfd18e2
...
@@ -19,16 +19,25 @@ package node
...
@@ -19,16 +19,25 @@ package node
import
(
import
(
"github.com/golang/glog"
"github.com/golang/glog"
storagev1alpha1
"k8s.io/api/storage/v1alpha1"
utilfeature
"k8s.io/apiserver/pkg/util/feature"
storageinformers
"k8s.io/client-go/informers/storage/v1alpha1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/cache"
api
"k8s.io/kubernetes/pkg/apis/core"
api
"k8s.io/kubernetes/pkg/apis/core"
coreinformers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion"
coreinformers
"k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion"
"k8s.io/kubernetes/pkg/features"
)
)
type
graphPopulator
struct
{
type
graphPopulator
struct
{
graph
*
Graph
graph
*
Graph
}
}
func
AddGraphEventHandlers
(
graph
*
Graph
,
pods
coreinformers
.
PodInformer
,
pvs
coreinformers
.
PersistentVolumeInformer
)
{
func
AddGraphEventHandlers
(
graph
*
Graph
,
pods
coreinformers
.
PodInformer
,
pvs
coreinformers
.
PersistentVolumeInformer
,
attachments
storageinformers
.
VolumeAttachmentInformer
,
)
{
g
:=
&
graphPopulator
{
g
:=
&
graphPopulator
{
graph
:
graph
,
graph
:
graph
,
}
}
...
@@ -44,6 +53,14 @@ func AddGraphEventHandlers(graph *Graph, pods coreinformers.PodInformer, pvs cor
...
@@ -44,6 +53,14 @@ func AddGraphEventHandlers(graph *Graph, pods coreinformers.PodInformer, pvs cor
UpdateFunc
:
g
.
updatePV
,
UpdateFunc
:
g
.
updatePV
,
DeleteFunc
:
g
.
deletePV
,
DeleteFunc
:
g
.
deletePV
,
})
})
if
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
CSIPersistentVolume
)
{
attachments
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
AddFunc
:
g
.
addVolumeAttachment
,
UpdateFunc
:
g
.
updateVolumeAttachment
,
DeleteFunc
:
g
.
deleteVolumeAttachment
,
})
}
}
}
func
(
g
*
graphPopulator
)
addPod
(
obj
interface
{})
{
func
(
g
*
graphPopulator
)
addPod
(
obj
interface
{})
{
...
@@ -106,3 +123,31 @@ func (g *graphPopulator) deletePV(obj interface{}) {
...
@@ -106,3 +123,31 @@ func (g *graphPopulator) deletePV(obj interface{}) {
}
}
g
.
graph
.
DeletePV
(
pv
.
Name
)
g
.
graph
.
DeletePV
(
pv
.
Name
)
}
}
func
(
g
*
graphPopulator
)
addVolumeAttachment
(
obj
interface
{})
{
g
.
updateVolumeAttachment
(
nil
,
obj
)
}
func
(
g
*
graphPopulator
)
updateVolumeAttachment
(
oldObj
,
obj
interface
{})
{
attachment
:=
obj
.
(
*
storagev1alpha1
.
VolumeAttachment
)
if
oldObj
!=
nil
{
// skip add if node name is identical
oldAttachment
:=
oldObj
.
(
*
storagev1alpha1
.
VolumeAttachment
)
if
oldAttachment
.
Spec
.
NodeName
==
attachment
.
Spec
.
NodeName
{
return
}
}
g
.
graph
.
AddVolumeAttachment
(
attachment
.
Name
,
attachment
.
Spec
.
NodeName
)
}
func
(
g
*
graphPopulator
)
deleteVolumeAttachment
(
obj
interface
{})
{
if
tombstone
,
ok
:=
obj
.
(
cache
.
DeletedFinalStateUnknown
);
ok
{
obj
=
tombstone
.
Obj
}
attachment
,
ok
:=
obj
.
(
*
api
.
PersistentVolume
)
if
!
ok
{
glog
.
Infof
(
"unexpected type %T"
,
obj
)
return
}
g
.
graph
.
DeleteVolumeAttachment
(
attachment
.
Name
)
}
plugin/pkg/auth/authorizer/node/node_authorizer.go
View file @
ecfd18e2
...
@@ -26,6 +26,7 @@ import (
...
@@ -26,6 +26,7 @@ import (
utilfeature
"k8s.io/apiserver/pkg/util/feature"
utilfeature
"k8s.io/apiserver/pkg/util/feature"
api
"k8s.io/kubernetes/pkg/apis/core"
api
"k8s.io/kubernetes/pkg/apis/core"
rbacapi
"k8s.io/kubernetes/pkg/apis/rbac"
rbacapi
"k8s.io/kubernetes/pkg/apis/rbac"
storageapi
"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"
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
...
@@ -48,6 +49,9 @@ type NodeAuthorizer struct {
...
@@ -48,6 +49,9 @@ type NodeAuthorizer struct {
graph
*
Graph
graph
*
Graph
identifier
nodeidentifier
.
NodeIdentifier
identifier
nodeidentifier
.
NodeIdentifier
nodeRules
[]
rbacapi
.
PolicyRule
nodeRules
[]
rbacapi
.
PolicyRule
// allows overriding for testing
features
utilfeature
.
FeatureGate
}
}
// NewAuthorizer returns a new node authorizer
// NewAuthorizer returns a new node authorizer
...
@@ -56,6 +60,7 @@ func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules
...
@@ -56,6 +60,7 @@ func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules
graph
:
graph
,
graph
:
graph
,
identifier
:
identifier
,
identifier
:
identifier
,
nodeRules
:
rules
,
nodeRules
:
rules
,
features
:
utilfeature
.
DefaultFeatureGate
,
}
}
}
}
...
@@ -64,6 +69,7 @@ var (
...
@@ -64,6 +69,7 @@ var (
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"
)
)
)
func
(
r
*
NodeAuthorizer
)
Authorize
(
attrs
authorizer
.
Attributes
)
(
authorizer
.
Decision
,
string
,
error
)
{
func
(
r
*
NodeAuthorizer
)
Authorize
(
attrs
authorizer
.
Attributes
)
(
authorizer
.
Decision
,
string
,
error
)
{
...
@@ -87,7 +93,7 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
...
@@ -87,7 +93,7 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
case
configMapResource
:
case
configMapResource
:
return
r
.
authorizeGet
(
nodeName
,
configMapVertexType
,
attrs
)
return
r
.
authorizeGet
(
nodeName
,
configMapVertexType
,
attrs
)
case
pvcResource
:
case
pvcResource
:
if
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
ExpandPersistentVolumes
)
{
if
r
.
features
.
Enabled
(
features
.
ExpandPersistentVolumes
)
{
if
attrs
.
GetSubresource
()
==
"status"
{
if
attrs
.
GetSubresource
()
==
"status"
{
return
r
.
authorizeStatusUpdate
(
nodeName
,
pvcVertexType
,
attrs
)
return
r
.
authorizeStatusUpdate
(
nodeName
,
pvcVertexType
,
attrs
)
}
}
...
@@ -95,6 +101,11 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
...
@@ -95,6 +101,11 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
return
r
.
authorizeGet
(
nodeName
,
pvcVertexType
,
attrs
)
return
r
.
authorizeGet
(
nodeName
,
pvcVertexType
,
attrs
)
case
pvResource
:
case
pvResource
:
return
r
.
authorizeGet
(
nodeName
,
pvVertexType
,
attrs
)
return
r
.
authorizeGet
(
nodeName
,
pvVertexType
,
attrs
)
case
vaResource
:
if
r
.
features
.
Enabled
(
features
.
CSIPersistentVolume
)
{
return
r
.
authorizeGet
(
nodeName
,
vaVertexType
,
attrs
)
}
return
authorizer
.
DecisionNoOpinion
,
fmt
.
Sprintf
(
"disabled by feature gate %s"
,
features
.
CSIPersistentVolume
),
nil
}
}
}
}
...
...
plugin/pkg/auth/authorizer/node/node_authorizer_test.go
View file @
ecfd18e2
...
@@ -24,14 +24,31 @@ import (
...
@@ -24,14 +24,31 @@ import (
"os"
"os"
storagev1alpha1
"k8s.io/api/storage/v1alpha1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/authorization/authorizer"
utilfeature
"k8s.io/apiserver/pkg/util/feature"
api
"k8s.io/kubernetes/pkg/apis/core"
api
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
)
)
var
(
csiEnabledFeature
=
utilfeature
.
NewFeatureGate
()
csiDisabledFeature
=
utilfeature
.
NewFeatureGate
()
)
func
init
()
{
if
err
:=
csiEnabledFeature
.
Add
(
map
[
utilfeature
.
Feature
]
utilfeature
.
FeatureSpec
{
features
.
CSIPersistentVolume
:
{
Default
:
true
}});
err
!=
nil
{
panic
(
err
)
}
if
err
:=
csiDisabledFeature
.
Add
(
map
[
utilfeature
.
Feature
]
utilfeature
.
FeatureSpec
{
features
.
CSIPersistentVolume
:
{
Default
:
false
}});
err
!=
nil
{
panic
(
err
)
}
}
func
TestAuthorizer
(
t
*
testing
.
T
)
{
func
TestAuthorizer
(
t
*
testing
.
T
)
{
g
:=
NewGraph
()
g
:=
NewGraph
()
...
@@ -39,6 +56,7 @@ func TestAuthorizer(t *testing.T) {
...
@@ -39,6 +56,7 @@ func TestAuthorizer(t *testing.T) {
nodes
:
2
,
nodes
:
2
,
namespaces
:
2
,
namespaces
:
2
,
podsPerNode
:
2
,
podsPerNode
:
2
,
attachmentsPerNode
:
1
,
sharedConfigMapsPerPod
:
0
,
sharedConfigMapsPerPod
:
0
,
uniqueConfigMapsPerPod
:
1
,
uniqueConfigMapsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
...
@@ -46,18 +64,19 @@ func TestAuthorizer(t *testing.T) {
...
@@ -46,18 +64,19 @@ func TestAuthorizer(t *testing.T) {
sharedPVCsPerPod
:
0
,
sharedPVCsPerPod
:
0
,
uniquePVCsPerPod
:
1
,
uniquePVCsPerPod
:
1
,
}
}
pods
,
pvs
:=
generate
(
opts
)
pods
,
pvs
,
attachments
:=
generate
(
opts
)
populate
(
g
,
pods
,
pvs
)
populate
(
g
,
pods
,
pvs
,
attachments
)
identifier
:=
nodeidentifier
.
NewDefaultNodeIdentifier
()
identifier
:=
nodeidentifier
.
NewDefaultNodeIdentifier
()
authz
:=
NewAuthorizer
(
g
,
identifier
,
bootstrappolicy
.
NodeRules
())
authz
:=
NewAuthorizer
(
g
,
identifier
,
bootstrappolicy
.
NodeRules
())
.
(
*
NodeAuthorizer
)
node0
:=
&
user
.
DefaultInfo
{
Name
:
"system:node:node0"
,
Groups
:
[]
string
{
"system:nodes"
}}
node0
:=
&
user
.
DefaultInfo
{
Name
:
"system:node:node0"
,
Groups
:
[]
string
{
"system:nodes"
}}
tests
:=
[]
struct
{
tests
:=
[]
struct
{
name
string
name
string
attrs
authorizer
.
AttributesRecord
attrs
authorizer
.
AttributesRecord
expect
authorizer
.
Decision
expect
authorizer
.
Decision
features
utilfeature
.
FeatureGate
}{
}{
{
{
name
:
"allowed configmap"
,
name
:
"allowed configmap"
,
...
@@ -115,10 +134,33 @@ func TestAuthorizer(t *testing.T) {
...
@@ -115,10 +134,33 @@ func TestAuthorizer(t *testing.T) {
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"persistentvolumes"
,
Name
:
"pv0-pod0-node1-ns0"
,
Namespace
:
""
},
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"persistentvolumes"
,
Name
:
"pv0-pod0-node1-ns0"
,
Namespace
:
""
},
expect
:
authorizer
.
DecisionNoOpinion
,
expect
:
authorizer
.
DecisionNoOpinion
,
},
},
{
name
:
"disallowed attachment - no relationship"
,
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"volumeattachments"
,
APIGroup
:
"storage.k8s.io"
,
Name
:
"attachment0-node1"
},
features
:
csiEnabledFeature
,
expect
:
authorizer
.
DecisionNoOpinion
,
},
{
name
:
"disallowed attachment - feature disabled"
,
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"volumeattachments"
,
APIGroup
:
"storage.k8s.io"
,
Name
:
"attachment0-node0"
},
features
:
csiDisabledFeature
,
expect
:
authorizer
.
DecisionNoOpinion
,
},
{
name
:
"allowed attachment - feature enabled"
,
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"volumeattachments"
,
APIGroup
:
"storage.k8s.io"
,
Name
:
"attachment0-node0"
},
features
:
csiEnabledFeature
,
expect
:
authorizer
.
DecisionAllow
,
},
}
}
for
_
,
tc
:=
range
tests
{
for
_
,
tc
:=
range
tests
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
if
tc
.
features
==
nil
{
authz
.
features
=
utilfeature
.
DefaultFeatureGate
}
else
{
authz
.
features
=
tc
.
features
}
decision
,
_
,
_
:=
authz
.
Authorize
(
tc
.
attrs
)
decision
,
_
,
_
:=
authz
.
Authorize
(
tc
.
attrs
)
if
decision
!=
tc
.
expect
{
if
decision
!=
tc
.
expect
{
t
.
Errorf
(
"expected %v, got %v"
,
tc
.
expect
,
decision
)
t
.
Errorf
(
"expected %v, got %v"
,
tc
.
expect
,
decision
)
...
@@ -204,6 +246,8 @@ type sampleDataOpts struct {
...
@@ -204,6 +246,8 @@ type sampleDataOpts struct {
podsPerNode
int
podsPerNode
int
attachmentsPerNode
int
sharedConfigMapsPerPod
int
sharedConfigMapsPerPod
int
sharedSecretsPerPod
int
sharedSecretsPerPod
int
sharedPVCsPerPod
int
sharedPVCsPerPod
int
...
@@ -218,6 +262,7 @@ func BenchmarkPopulationAllocation(b *testing.B) {
...
@@ -218,6 +262,7 @@ func BenchmarkPopulationAllocation(b *testing.B) {
nodes
:
500
,
nodes
:
500
,
namespaces
:
200
,
namespaces
:
200
,
podsPerNode
:
200
,
podsPerNode
:
200
,
attachmentsPerNode
:
20
,
sharedConfigMapsPerPod
:
0
,
sharedConfigMapsPerPod
:
0
,
uniqueConfigMapsPerPod
:
1
,
uniqueConfigMapsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
...
@@ -226,12 +271,12 @@ func BenchmarkPopulationAllocation(b *testing.B) {
...
@@ -226,12 +271,12 @@ func BenchmarkPopulationAllocation(b *testing.B) {
uniquePVCsPerPod
:
1
,
uniquePVCsPerPod
:
1
,
}
}
pods
,
pvs
:=
generate
(
opts
)
pods
,
pvs
,
attachments
:=
generate
(
opts
)
b
.
ResetTimer
()
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
g
:=
NewGraph
()
g
:=
NewGraph
()
populate
(
g
,
pods
,
pvs
)
populate
(
g
,
pods
,
pvs
,
attachments
)
}
}
}
}
...
@@ -248,6 +293,7 @@ func BenchmarkPopulationRetention(b *testing.B) {
...
@@ -248,6 +293,7 @@ func BenchmarkPopulationRetention(b *testing.B) {
nodes
:
500
,
nodes
:
500
,
namespaces
:
200
,
namespaces
:
200
,
podsPerNode
:
200
,
podsPerNode
:
200
,
attachmentsPerNode
:
20
,
sharedConfigMapsPerPod
:
0
,
sharedConfigMapsPerPod
:
0
,
uniqueConfigMapsPerPod
:
1
,
uniqueConfigMapsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
...
@@ -256,14 +302,14 @@ func BenchmarkPopulationRetention(b *testing.B) {
...
@@ -256,14 +302,14 @@ func BenchmarkPopulationRetention(b *testing.B) {
uniquePVCsPerPod
:
1
,
uniquePVCsPerPod
:
1
,
}
}
pods
,
pvs
:=
generate
(
opts
)
pods
,
pvs
,
attachments
:=
generate
(
opts
)
// Garbage collect before the first iteration
// Garbage collect before the first iteration
runtime
.
GC
()
runtime
.
GC
()
b
.
ResetTimer
()
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
g
:=
NewGraph
()
g
:=
NewGraph
()
populate
(
g
,
pods
,
pvs
)
populate
(
g
,
pods
,
pvs
,
attachments
)
if
i
==
0
{
if
i
==
0
{
f
,
_
:=
os
.
Create
(
"BenchmarkPopulationRetention.profile"
)
f
,
_
:=
os
.
Create
(
"BenchmarkPopulationRetention.profile"
)
...
@@ -283,6 +329,7 @@ func BenchmarkAuthorization(b *testing.B) {
...
@@ -283,6 +329,7 @@ func BenchmarkAuthorization(b *testing.B) {
nodes
:
500
,
nodes
:
500
,
namespaces
:
200
,
namespaces
:
200
,
podsPerNode
:
200
,
podsPerNode
:
200
,
attachmentsPerNode
:
20
,
sharedConfigMapsPerPod
:
0
,
sharedConfigMapsPerPod
:
0
,
uniqueConfigMapsPerPod
:
1
,
uniqueConfigMapsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
sharedSecretsPerPod
:
1
,
...
@@ -290,18 +337,19 @@ func BenchmarkAuthorization(b *testing.B) {
...
@@ -290,18 +337,19 @@ func BenchmarkAuthorization(b *testing.B) {
sharedPVCsPerPod
:
0
,
sharedPVCsPerPod
:
0
,
uniquePVCsPerPod
:
1
,
uniquePVCsPerPod
:
1
,
}
}
pods
,
pvs
:=
generate
(
opts
)
pods
,
pvs
,
attachments
:=
generate
(
opts
)
populate
(
g
,
pods
,
pvs
)
populate
(
g
,
pods
,
pvs
,
attachments
)
identifier
:=
nodeidentifier
.
NewDefaultNodeIdentifier
()
identifier
:=
nodeidentifier
.
NewDefaultNodeIdentifier
()
authz
:=
NewAuthorizer
(
g
,
identifier
,
bootstrappolicy
.
NodeRules
())
authz
:=
NewAuthorizer
(
g
,
identifier
,
bootstrappolicy
.
NodeRules
())
.
(
*
NodeAuthorizer
)
node0
:=
&
user
.
DefaultInfo
{
Name
:
"system:node:node0"
,
Groups
:
[]
string
{
"system:nodes"
}}
node0
:=
&
user
.
DefaultInfo
{
Name
:
"system:node:node0"
,
Groups
:
[]
string
{
"system:nodes"
}}
tests
:=
[]
struct
{
tests
:=
[]
struct
{
name
string
name
string
attrs
authorizer
.
AttributesRecord
attrs
authorizer
.
AttributesRecord
expect
authorizer
.
Decision
expect
authorizer
.
Decision
features
utilfeature
.
FeatureGate
}{
}{
{
{
name
:
"allowed configmap"
,
name
:
"allowed configmap"
,
...
@@ -343,10 +391,33 @@ func BenchmarkAuthorization(b *testing.B) {
...
@@ -343,10 +391,33 @@ func BenchmarkAuthorization(b *testing.B) {
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"persistentvolumes"
,
Name
:
"pv0-pod0-node1-ns0"
,
Namespace
:
""
},
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"persistentvolumes"
,
Name
:
"pv0-pod0-node1-ns0"
,
Namespace
:
""
},
expect
:
authorizer
.
DecisionNoOpinion
,
expect
:
authorizer
.
DecisionNoOpinion
,
},
},
{
name
:
"disallowed attachment - no relationship"
,
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"volumeattachments"
,
APIGroup
:
"storage.k8s.io"
,
Name
:
"attachment0-node1"
},
features
:
csiEnabledFeature
,
expect
:
authorizer
.
DecisionNoOpinion
,
},
{
name
:
"disallowed attachment - feature disabled"
,
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"volumeattachments"
,
APIGroup
:
"storage.k8s.io"
,
Name
:
"attachment0-node0"
},
features
:
csiDisabledFeature
,
expect
:
authorizer
.
DecisionNoOpinion
,
},
{
name
:
"allowed attachment - feature enabled"
,
attrs
:
authorizer
.
AttributesRecord
{
User
:
node0
,
ResourceRequest
:
true
,
Verb
:
"get"
,
Resource
:
"volumeattachments"
,
APIGroup
:
"storage.k8s.io"
,
Name
:
"attachment0-node0"
},
features
:
csiEnabledFeature
,
expect
:
authorizer
.
DecisionAllow
,
},
}
}
b
.
ResetTimer
()
b
.
ResetTimer
()
for
_
,
tc
:=
range
tests
{
for
_
,
tc
:=
range
tests
{
if
tc
.
features
==
nil
{
authz
.
features
=
utilfeature
.
DefaultFeatureGate
}
else
{
authz
.
features
=
tc
.
features
}
b
.
Run
(
tc
.
name
,
func
(
b
*
testing
.
B
)
{
b
.
Run
(
tc
.
name
,
func
(
b
*
testing
.
B
)
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
decision
,
_
,
_
:=
authz
.
Authorize
(
tc
.
attrs
)
decision
,
_
,
_
:=
authz
.
Authorize
(
tc
.
attrs
)
...
@@ -358,7 +429,7 @@ func BenchmarkAuthorization(b *testing.B) {
...
@@ -358,7 +429,7 @@ func BenchmarkAuthorization(b *testing.B) {
}
}
}
}
func
populate
(
graph
*
Graph
,
pods
[]
*
api
.
Pod
,
pvs
[]
*
api
.
PersistentVolume
)
{
func
populate
(
graph
*
Graph
,
pods
[]
*
api
.
Pod
,
pvs
[]
*
api
.
PersistentVolume
,
attachments
[]
*
storagev1alpha1
.
VolumeAttachment
)
{
p
:=
&
graphPopulator
{}
p
:=
&
graphPopulator
{}
p
.
graph
=
graph
p
.
graph
=
graph
for
_
,
pod
:=
range
pods
{
for
_
,
pod
:=
range
pods
{
...
@@ -367,15 +438,19 @@ func populate(graph *Graph, pods []*api.Pod, pvs []*api.PersistentVolume) {
...
@@ -367,15 +438,19 @@ func populate(graph *Graph, pods []*api.Pod, pvs []*api.PersistentVolume) {
for
_
,
pv
:=
range
pvs
{
for
_
,
pv
:=
range
pvs
{
p
.
addPV
(
pv
)
p
.
addPV
(
pv
)
}
}
for
_
,
attachment
:=
range
attachments
{
p
.
addVolumeAttachment
(
attachment
)
}
}
}
// generate creates sample pods and persistent volumes based on the provided options.
// generate creates sample pods and persistent volumes based on the provided options.
// the secret/configmap/pvc/node references in the pod and pv objects are named to indicate the connections between the objects.
// the secret/configmap/pvc/node references in the pod and pv objects are named to indicate the connections between the objects.
// for example, secret0-pod0-node0 is a secret referenced by pod0 which is bound to node0.
// for example, secret0-pod0-node0 is a secret referenced by pod0 which is bound to node0.
// when populated into the graph, the node authorizer should allow node0 to access that secret, but not node1.
// when populated into the graph, the node authorizer should allow node0 to access that secret, but not node1.
func
generate
(
opts
sampleDataOpts
)
([]
*
api
.
Pod
,
[]
*
api
.
PersistentVolume
)
{
func
generate
(
opts
sampleDataOpts
)
([]
*
api
.
Pod
,
[]
*
api
.
PersistentVolume
,
[]
*
storagev1alpha1
.
VolumeAttachment
)
{
pods
:=
make
([]
*
api
.
Pod
,
0
,
opts
.
nodes
*
opts
.
podsPerNode
)
pods
:=
make
([]
*
api
.
Pod
,
0
,
opts
.
nodes
*
opts
.
podsPerNode
)
pvs
:=
make
([]
*
api
.
PersistentVolume
,
0
,
(
opts
.
nodes
*
opts
.
podsPerNode
*
opts
.
uniquePVCsPerPod
)
+
(
opts
.
sharedPVCsPerPod
*
opts
.
namespaces
))
pvs
:=
make
([]
*
api
.
PersistentVolume
,
0
,
(
opts
.
nodes
*
opts
.
podsPerNode
*
opts
.
uniquePVCsPerPod
)
+
(
opts
.
sharedPVCsPerPod
*
opts
.
namespaces
))
attachments
:=
make
([]
*
storagev1alpha1
.
VolumeAttachment
,
0
,
opts
.
nodes
*
opts
.
attachmentsPerNode
)
for
n
:=
0
;
n
<
opts
.
nodes
;
n
++
{
for
n
:=
0
;
n
<
opts
.
nodes
;
n
++
{
nodeName
:=
fmt
.
Sprintf
(
"node%d"
,
n
)
nodeName
:=
fmt
.
Sprintf
(
"node%d"
,
n
)
...
@@ -432,6 +507,12 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
...
@@ -432,6 +507,12 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
pods
=
append
(
pods
,
pod
)
pods
=
append
(
pods
,
pod
)
}
}
for
a
:=
0
;
a
<
opts
.
attachmentsPerNode
;
a
++
{
attachment
:=
&
storagev1alpha1
.
VolumeAttachment
{}
attachment
.
Name
=
fmt
.
Sprintf
(
"attachment%d-%s"
,
a
,
nodeName
)
attachment
.
Spec
.
NodeName
=
nodeName
attachments
=
append
(
attachments
,
attachment
)
}
}
}
return
pods
,
pvs
return
pods
,
pvs
,
attachments
}
}
test/integration/auth/BUILD
View file @
ecfd18e2
...
@@ -52,6 +52,7 @@ go_test(
...
@@ -52,6 +52,7 @@ go_test(
"//test/integration/framework:go_default_library",
"//test/integration/framework:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/authentication/v1beta1:go_default_library",
"//vendor/k8s.io/api/authentication/v1beta1:go_default_library",
"//vendor/k8s.io/api/storage/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...
@@ -69,6 +70,7 @@ go_test(
...
@@ -69,6 +70,7 @@ go_test(
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest:go_default_library",
...
...
test/integration/auth/node_test.go
View file @
ecfd18e2
...
@@ -23,6 +23,7 @@ import (
...
@@ -23,6 +23,7 @@ import (
"testing"
"testing"
"time"
"time"
storagev1alpha1
"k8s.io/api/storage/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
...
@@ -31,9 +32,11 @@ import (
...
@@ -31,9 +32,11 @@ import (
"k8s.io/apiserver/pkg/authentication/request/bearertoken"
"k8s.io/apiserver/pkg/authentication/request/bearertoken"
"k8s.io/apiserver/pkg/authentication/token/tokenfile"
"k8s.io/apiserver/pkg/authentication/token/tokenfile"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authentication/user"
serverstorage
"k8s.io/apiserver/pkg/server/storage"
utilfeature
"k8s.io/apiserver/pkg/util/feature"
utilfeature
"k8s.io/apiserver/pkg/util/feature"
utilfeaturetesting
"k8s.io/apiserver/pkg/util/feature/testing"
utilfeaturetesting
"k8s.io/apiserver/pkg/util/feature/testing"
versionedinformers
"k8s.io/client-go/informers"
versionedinformers
"k8s.io/client-go/informers"
externalclientset
"k8s.io/client-go/kubernetes"
restclient
"k8s.io/client-go/rest"
restclient
"k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api
"k8s.io/kubernetes/pkg/apis/core"
api
"k8s.io/kubernetes/pkg/apis/core"
...
@@ -76,6 +79,9 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -76,6 +79,9 @@ func TestNodeAuthorizer(t *testing.T) {
informerFactory
:=
informers
.
NewSharedInformerFactory
(
superuserClient
,
time
.
Minute
)
informerFactory
:=
informers
.
NewSharedInformerFactory
(
superuserClient
,
time
.
Minute
)
versionedInformerFactory
:=
versionedinformers
.
NewSharedInformerFactory
(
superuserClientExternal
,
time
.
Minute
)
versionedInformerFactory
:=
versionedinformers
.
NewSharedInformerFactory
(
superuserClientExternal
,
time
.
Minute
)
// Enabled CSIPersistentVolume feature at startup so volumeattachments get watched
defer
utilfeaturetesting
.
SetFeatureGateDuringTest
(
t
,
utilfeature
.
DefaultFeatureGate
,
features
.
CSIPersistentVolume
,
true
)()
// Set up Node+RBAC authorizer
// Set up Node+RBAC authorizer
authorizerConfig
:=
&
authorizer
.
AuthorizationConfig
{
authorizerConfig
:=
&
authorizer
.
AuthorizationConfig
{
AuthorizationModes
:
[]
string
{
"Node"
,
"RBAC"
},
AuthorizationModes
:
[]
string
{
"Node"
,
"RBAC"
},
...
@@ -99,6 +105,10 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -99,6 +105,10 @@ func TestNodeAuthorizer(t *testing.T) {
masterConfig
.
GenericConfig
.
Authenticator
=
authenticator
masterConfig
.
GenericConfig
.
Authenticator
=
authenticator
masterConfig
.
GenericConfig
.
Authorizer
=
nodeRBACAuthorizer
masterConfig
.
GenericConfig
.
Authorizer
=
nodeRBACAuthorizer
masterConfig
.
GenericConfig
.
AdmissionControl
=
nodeRestrictionAdmission
masterConfig
.
GenericConfig
.
AdmissionControl
=
nodeRestrictionAdmission
// enable testing volume attachments
masterConfig
.
ExtraConfig
.
APIResourceConfigSource
.
(
*
serverstorage
.
ResourceConfig
)
.
EnableVersions
(
storagev1alpha1
.
SchemeGroupVersion
)
_
,
_
,
closeFn
:=
framework
.
RunAMasterUsingServer
(
masterConfig
,
apiServer
,
h
)
_
,
_
,
closeFn
:=
framework
.
RunAMasterUsingServer
(
masterConfig
,
apiServer
,
h
)
defer
closeFn
()
defer
closeFn
()
...
@@ -129,6 +139,17 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -129,6 +139,17 @@ func TestNodeAuthorizer(t *testing.T) {
if
_
,
err
:=
superuserClient
.
Core
()
.
ConfigMaps
(
"ns"
)
.
Create
(
&
api
.
ConfigMap
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"myconfigmap"
}});
err
!=
nil
{
if
_
,
err
:=
superuserClient
.
Core
()
.
ConfigMaps
(
"ns"
)
.
Create
(
&
api
.
ConfigMap
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"myconfigmap"
}});
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
pvName
:=
"mypv"
if
_
,
err
:=
superuserClientExternal
.
StorageV1alpha1
()
.
VolumeAttachments
()
.
Create
(
&
storagev1alpha1
.
VolumeAttachment
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"myattachment"
},
Spec
:
storagev1alpha1
.
VolumeAttachmentSpec
{
Attacher
:
"foo"
,
Source
:
storagev1alpha1
.
VolumeAttachmentSource
{
PersistentVolumeName
:
&
pvName
},
NodeName
:
"node2"
,
},
});
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
_
,
err
:=
superuserClient
.
Core
()
.
PersistentVolumeClaims
(
"ns"
)
.
Create
(
&
api
.
PersistentVolumeClaim
{
if
_
,
err
:=
superuserClient
.
Core
()
.
PersistentVolumeClaims
(
"ns"
)
.
Create
(
&
api
.
PersistentVolumeClaim
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"mypvc"
},
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"mypvc"
},
Spec
:
api
.
PersistentVolumeClaimSpec
{
Spec
:
api
.
PersistentVolumeClaimSpec
{
...
@@ -181,6 +202,12 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -181,6 +202,12 @@ func TestNodeAuthorizer(t *testing.T) {
return
err
return
err
}
}
}
}
getVolumeAttachment
:=
func
(
client
externalclientset
.
Interface
)
func
()
error
{
return
func
()
error
{
_
,
err
:=
client
.
StorageV1alpha1
()
.
VolumeAttachments
()
.
Get
(
"myattachment"
,
metav1
.
GetOptions
{})
return
err
}
}
createNode2NormalPod
:=
func
(
client
clientset
.
Interface
)
func
()
error
{
createNode2NormalPod
:=
func
(
client
clientset
.
Interface
)
func
()
error
{
return
func
()
error
{
return
func
()
error
{
...
@@ -307,8 +334,8 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -307,8 +334,8 @@ func TestNodeAuthorizer(t *testing.T) {
}
}
nodeanonClient
,
_
:=
clientsetForToken
(
tokenNodeUnknown
,
clientConfig
)
nodeanonClient
,
_
:=
clientsetForToken
(
tokenNodeUnknown
,
clientConfig
)
node1Client
,
_
:=
clientsetForToken
(
tokenNode1
,
clientConfig
)
node1Client
,
node1ClientExternal
:=
clientsetForToken
(
tokenNode1
,
clientConfig
)
node2Client
,
_
:=
clientsetForToken
(
tokenNode2
,
clientConfig
)
node2Client
,
node2ClientExternal
:=
clientsetForToken
(
tokenNode2
,
clientConfig
)
// all node requests from node1 and unknown node fail
// all node requests from node1 and unknown node fail
expectForbidden
(
t
,
getSecret
(
nodeanonClient
))
expectForbidden
(
t
,
getSecret
(
nodeanonClient
))
...
@@ -405,32 +432,40 @@ func TestNodeAuthorizer(t *testing.T) {
...
@@ -405,32 +432,40 @@ func TestNodeAuthorizer(t *testing.T) {
// re-create a pod as an admin to add object references
// re-create a pod as an admin to add object references
expectAllowed
(
t
,
createNode2NormalPod
(
superuserClient
))
expectAllowed
(
t
,
createNode2NormalPod
(
superuserClient
))
// With ExpandPersistentVolumes feature disabled
// ExpandPersistentVolumes feature disabled
defer
utilfeaturetesting
.
SetFeatureGateDuringTest
(
t
,
utilfeature
.
DefaultFeatureGate
,
features
.
ExpandPersistentVolumes
,
false
)()
defer
utilfeaturetesting
.
SetFeatureGateDuringTest
(
t
,
utilfeature
.
DefaultFeatureGate
,
features
.
ExpandPersistentVolumes
,
false
)()
// node->pvc relationship not established
expectForbidden
(
t
,
updatePVCCapacity
(
node1Client
))
expectForbidden
(
t
,
updatePVCCapacity
(
node1Client
))
// node->pvc relationship established but feature is disabled
expectForbidden
(
t
,
updatePVCCapacity
(
node2Client
))
expectForbidden
(
t
,
updatePVCCapacity
(
node2Client
))
//
Enabled ExpandPersistentVolumes feature
//
ExpandPersistentVolumes feature enabled
defer
utilfeaturetesting
.
SetFeatureGateDuringTest
(
t
,
utilfeature
.
DefaultFeatureGate
,
features
.
ExpandPersistentVolumes
,
true
)()
defer
utilfeaturetesting
.
SetFeatureGateDuringTest
(
t
,
utilfeature
.
DefaultFeatureGate
,
features
.
ExpandPersistentVolumes
,
true
)()
// Node->pvc relationship not established
expectForbidden
(
t
,
updatePVCCapacity
(
node1Client
))
expectForbidden
(
t
,
updatePVCCapacity
(
node1Client
))
// node->pvc relationship established and feature is enabled
expectAllowed
(
t
,
updatePVCCapacity
(
node2Client
))
expectAllowed
(
t
,
updatePVCCapacity
(
node2Client
))
// node->pvc relationship established but updating phase
expectForbidden
(
t
,
updatePVCPhase
(
node2Client
))
expectForbidden
(
t
,
updatePVCPhase
(
node2Client
))
// Disabled CSIPersistentVolume feature
defer
utilfeaturetesting
.
SetFeatureGateDuringTest
(
t
,
utilfeature
.
DefaultFeatureGate
,
features
.
CSIPersistentVolume
,
false
)()
expectForbidden
(
t
,
getVolumeAttachment
(
node1ClientExternal
))
expectForbidden
(
t
,
getVolumeAttachment
(
node2ClientExternal
))
// Enabled CSIPersistentVolume feature
defer
utilfeaturetesting
.
SetFeatureGateDuringTest
(
t
,
utilfeature
.
DefaultFeatureGate
,
features
.
CSIPersistentVolume
,
true
)()
expectForbidden
(
t
,
getVolumeAttachment
(
node1ClientExternal
))
expectAllowed
(
t
,
getVolumeAttachment
(
node2ClientExternal
))
}
}
// expect executes a function a set number of times until it either returns the
// expect executes a function a set number of times until it either returns the
// expected error or executes too many times. It returns if the retries timed
// expected error or executes too many times. It returns if the retries timed
// out and the last error returned by the method.
// out and the last error returned by the method.
func
expect
(
f
func
()
error
,
wantErr
func
(
error
)
bool
)
(
timeout
bool
,
lastErr
error
)
{
func
expect
(
t
*
testing
.
T
,
f
func
()
error
,
wantErr
func
(
error
)
bool
)
(
timeout
bool
,
lastErr
error
)
{
t
.
Helper
()
err
:=
wait
.
PollImmediate
(
time
.
Second
,
30
*
time
.
Second
,
func
()
(
bool
,
error
)
{
err
:=
wait
.
PollImmediate
(
time
.
Second
,
30
*
time
.
Second
,
func
()
(
bool
,
error
)
{
t
.
Helper
()
lastErr
=
f
()
lastErr
=
f
()
if
wantErr
(
lastErr
)
{
if
wantErr
(
lastErr
)
{
return
true
,
nil
return
true
,
nil
}
}
t
.
Logf
(
"unexpected response, will retry: %v"
,
lastErr
)
return
false
,
nil
return
false
,
nil
})
})
return
err
==
nil
,
lastErr
return
err
==
nil
,
lastErr
...
@@ -438,21 +473,21 @@ func expect(f func() error, wantErr func(error) bool) (timeout bool, lastErr err
...
@@ -438,21 +473,21 @@ func expect(f func() error, wantErr func(error) bool) (timeout bool, lastErr err
func
expectForbidden
(
t
*
testing
.
T
,
f
func
()
error
)
{
func
expectForbidden
(
t
*
testing
.
T
,
f
func
()
error
)
{
t
.
Helper
()
t
.
Helper
()
if
ok
,
err
:=
expect
(
f
,
errors
.
IsForbidden
);
!
ok
{
if
ok
,
err
:=
expect
(
t
,
f
,
errors
.
IsForbidden
);
!
ok
{
t
.
Errorf
(
"Expected forbidden error, got %v"
,
err
)
t
.
Errorf
(
"Expected forbidden error, got %v"
,
err
)
}
}
}
}
func
expectNotFound
(
t
*
testing
.
T
,
f
func
()
error
)
{
func
expectNotFound
(
t
*
testing
.
T
,
f
func
()
error
)
{
t
.
Helper
()
t
.
Helper
()
if
ok
,
err
:=
expect
(
f
,
errors
.
IsNotFound
);
!
ok
{
if
ok
,
err
:=
expect
(
t
,
f
,
errors
.
IsNotFound
);
!
ok
{
t
.
Errorf
(
"Expected notfound error, got %v"
,
err
)
t
.
Errorf
(
"Expected notfound error, got %v"
,
err
)
}
}
}
}
func
expectAllowed
(
t
*
testing
.
T
,
f
func
()
error
)
{
func
expectAllowed
(
t
*
testing
.
T
,
f
func
()
error
)
{
t
.
Helper
()
t
.
Helper
()
if
ok
,
err
:=
expect
(
f
,
func
(
e
error
)
bool
{
return
e
==
nil
});
!
ok
{
if
ok
,
err
:=
expect
(
t
,
f
,
func
(
e
error
)
bool
{
return
e
==
nil
});
!
ok
{
t
.
Errorf
(
"Expected no error, got %v"
,
err
)
t
.
Errorf
(
"Expected no error, got %v"
,
err
)
}
}
}
}
test/integration/framework/master_utils.go
View file @
ecfd18e2
...
@@ -300,7 +300,10 @@ func NewMasterConfig() *master.Config {
...
@@ -300,7 +300,10 @@ func NewMasterConfig() *master.Config {
// FIXME (soltysh): this GroupVersionResource override should be configurable
// FIXME (soltysh): this GroupVersionResource override should be configurable
// we need to set both for the whole group and for cronjobs, separately
// we need to set both for the whole group and for cronjobs, separately
resourceEncoding
.
SetVersionEncoding
(
batch
.
GroupName
,
*
testapi
.
Batch
.
GroupVersion
(),
schema
.
GroupVersion
{
Group
:
batch
.
GroupName
,
Version
:
runtime
.
APIVersionInternal
})
resourceEncoding
.
SetVersionEncoding
(
batch
.
GroupName
,
*
testapi
.
Batch
.
GroupVersion
(),
schema
.
GroupVersion
{
Group
:
batch
.
GroupName
,
Version
:
runtime
.
APIVersionInternal
})
resourceEncoding
.
SetResourceEncoding
(
schema
.
GroupResource
{
Group
:
"batch"
,
Resource
:
"cronjobs"
},
schema
.
GroupVersion
{
Group
:
batch
.
GroupName
,
Version
:
"v1beta1"
},
schema
.
GroupVersion
{
Group
:
batch
.
GroupName
,
Version
:
runtime
.
APIVersionInternal
})
resourceEncoding
.
SetResourceEncoding
(
schema
.
GroupResource
{
Group
:
batch
.
GroupName
,
Resource
:
"cronjobs"
},
schema
.
GroupVersion
{
Group
:
batch
.
GroupName
,
Version
:
"v1beta1"
},
schema
.
GroupVersion
{
Group
:
batch
.
GroupName
,
Version
:
runtime
.
APIVersionInternal
})
// volumeattachments only exist in storage.k8s.io/v1alpha1
resourceEncoding
.
SetVersionEncoding
(
storage
.
GroupName
,
*
testapi
.
Storage
.
GroupVersion
(),
schema
.
GroupVersion
{
Group
:
storage
.
GroupName
,
Version
:
runtime
.
APIVersionInternal
})
resourceEncoding
.
SetResourceEncoding
(
schema
.
GroupResource
{
Group
:
storage
.
GroupName
,
Resource
:
"volumeattachments"
},
schema
.
GroupVersion
{
Group
:
storage
.
GroupName
,
Version
:
"v1alpha1"
},
schema
.
GroupVersion
{
Group
:
storage
.
GroupName
,
Version
:
runtime
.
APIVersionInternal
})
storageFactory
:=
serverstorage
.
NewDefaultStorageFactory
(
etcdOptions
.
StorageConfig
,
runtime
.
ContentTypeJSON
,
ns
,
resourceEncoding
,
master
.
DefaultAPIResourceConfigSource
(),
nil
)
storageFactory
:=
serverstorage
.
NewDefaultStorageFactory
(
etcdOptions
.
StorageConfig
,
runtime
.
ContentTypeJSON
,
ns
,
resourceEncoding
,
master
.
DefaultAPIResourceConfigSource
(),
nil
)
storageFactory
.
SetSerializer
(
storageFactory
.
SetSerializer
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment