Skip to content

Commit

Permalink
fix: Validate use verb for PodSecurityPolicies (#68)
Browse files Browse the repository at this point in the history
Resolves: #63

Signed-off-by: Daniel Pacak <[email protected]>
  • Loading branch information
danielpacak authored Feb 20, 2020
1 parent 3b55776 commit f78ee94
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 43 deletions.
3 changes: 3 additions & 0 deletions pkg/cmd/resource_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ func (rv *resourceResolver) isVerbSupportedBy(verb string, resource apismeta.API
if verb == rbac.VerbAll {
return true
}
if resource.Name == "podsecuritypolicies" && verb == "use" {
return true
}
supported := false
for _, v := range resource.Verbs {
if v == verb {
Expand Down
108 changes: 65 additions & 43 deletions pkg/cmd/resource_resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ func TestResourceResolver_Resolve(t *testing.T) {
podsGR := schema.GroupResource{Resource: "pods"}
deploymentsGVR := schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"}
deploymentsGR := schema.GroupResource{Group: "extensions", Resource: "deployments"}
pspGVR := schema.GroupVersionResource{Group: "policy", Version: "v1beta1", Resource: "podsecuritypolicies"}
pspGV := schema.GroupResource{Group: "policy", Resource: "podsecuritypolicies"}

client := fake.NewSimpleClientset()

Expand All @@ -47,6 +49,12 @@ func TestResourceResolver_Resolve(t *testing.T) {
{Group: "extensions", Version: "v1beta1", Name: "deployments/scale", Verbs: []string{"update", "patch"}},
},
},
{
GroupVersion: "policy/v1beta1",
APIResources: []apismeta.APIResource{
{Group: "policy", Version: "v1beta1", Name: "podsecuritypolicies", Verbs: []string{"list", "get"}},
},
},
}

type mappingResult struct {
Expand All @@ -56,111 +64,125 @@ func TestResourceResolver_Resolve(t *testing.T) {
returnError error
}

type expected struct {
gr schema.GroupResource
err error
}

data := []struct {
scenario string
testCases := []struct {
name string
action Action
mappingResult *mappingResult
expected
expectedGR schema.GroupResource
expectedError error
}{
{
scenario: "A",
action: Action{Verb: "list", Resource: "pods"},
name: "A",
action: Action{Verb: "list", Resource: "pods"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "pods"},
returnGVR: podsGVR,
},
expected: expected{gr: podsGR},
expectedGR: podsGR,
},
{
scenario: "B",
action: Action{Verb: "list", Resource: "po"},
name: "B",
action: Action{Verb: "list", Resource: "po"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "po"},
returnGVR: podsGVR,
},
expected: expected{gr: podsGR},
expectedGR: podsGR,
},
{
scenario: "C",
action: Action{Verb: "eat", Resource: "pods"},
name: "C",
action: Action{Verb: "eat", Resource: "pods"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "pods"},
returnGVR: podsGVR,
},
expected: expected{err: errors.New("the \"pods\" resource does not support the \"eat\" verb, only [list create delete]")},
expectedError: errors.New("the \"pods\" resource does not support the \"eat\" verb, only [list create delete]"),
},
{
scenario: "D",
action: Action{Verb: "list", Resource: "deployments.extensions"},
name: "D",
action: Action{Verb: "list", Resource: "deployments.extensions"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Group: "extensions", Version: "", Resource: "deployments"},
returnGVR: deploymentsGVR,
},
expected: expected{gr: deploymentsGR},
expectedGR: deploymentsGR,
},
{
scenario: "E",
action: Action{Verb: "get", Resource: "pods", SubResource: "log"},
name: "E",
action: Action{Verb: "get", Resource: "pods", SubResource: "log"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "pods"},
returnGVR: podsGVR,
},
expected: expected{gr: podsGR},
expectedGR: podsGR,
},
{
scenario: "F",
action: Action{Verb: "get", Resource: "pods", SubResource: "logz"},
name: "F",
action: Action{Verb: "get", Resource: "pods", SubResource: "logz"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "pods"},
returnGVR: podsGVR,
},
expected: expected{err: errors.New("the server doesn't have a resource type \"pods/logz\"")},
expectedError: errors.New("the server doesn't have a resource type \"pods/logz\""),
},
{
scenario: "G",
action: Action{Verb: "list", Resource: "bees"},
name: "G",
action: Action{Verb: "list", Resource: "bees"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "bees"},
returnError: errors.New("mapping failed"),
},
expected: expected{err: errors.New("the server doesn't have a resource type \"bees\"")},
expectedError: errors.New("the server doesn't have a resource type \"bees\""),
},
{
scenario: "H",
action: Action{Verb: rbac.VerbAll, Resource: "pods"},
name: "H",
action: Action{Verb: rbac.VerbAll, Resource: "pods"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "pods"},
returnGVR: podsGVR,
},
expected: expected{gr: podsGR},
expectedGR: podsGR,
},
{
name: "I",
action: Action{Verb: "list", Resource: rbac.ResourceAll},
expectedGR: schema.GroupResource{Resource: rbac.ResourceAll},
},
{
name: "Should resolve psp",
action: Action{Verb: "use", Resource: "psp"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "psp"},
returnGVR: pspGVR,
},
expectedGR: pspGV,
},
{
scenario: "I",
action: Action{Verb: "list", Resource: rbac.ResourceAll},
expected: expected{gr: schema.GroupResource{Resource: rbac.ResourceAll}},
name: "Should return error when psp verb is not supported",
action: Action{Verb: "cook", Resource: "psp"},
mappingResult: &mappingResult{
argGVR: schema.GroupVersionResource{Resource: "psp"},
returnGVR: pspGVR,
},
expectedError: errors.New("the \"podsecuritypolicies\" resource does not support the \"cook\" verb, only [list get]"),
},
}

for _, tt := range data {
t.Run(tt.scenario, func(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mapper := new(mapperMock)

if tt.mappingResult != nil {
mapper.On("ResourceFor", tt.mappingResult.argGVR).
Return(tt.mappingResult.returnGVR, tt.mappingResult.returnError)
if tc.mappingResult != nil {
mapper.On("ResourceFor", tc.mappingResult.argGVR).
Return(tc.mappingResult.returnGVR, tc.mappingResult.returnError)
}

resolver := NewResourceResolver(client.Discovery(), mapper)

resource, err := resolver.Resolve(tt.action.Verb, tt.action.Resource, tt.action.SubResource)
resource, err := resolver.Resolve(tc.action.Verb, tc.action.Resource, tc.action.SubResource)

assert.Equal(t, tt.expected.err, err)
assert.Equal(t, tt.expected.gr, resource)
assert.Equal(t, tc.expectedError, err)
assert.Equal(t, tc.expectedGR, resource)

mapper.AssertExpectations(t)
})
Expand Down

0 comments on commit f78ee94

Please sign in to comment.