2014-10-06 23:11:04 +00:00
|
|
|
/*
|
2016-06-03 00:25:58 +00:00
|
|
|
Copyright 2014 The Kubernetes Authors.
|
2014-10-06 23:11:04 +00:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package abac
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2017-07-14 03:24:27 +00:00
|
|
|
"reflect"
|
2014-10-06 23:11:04 +00:00
|
|
|
"testing"
|
|
|
|
|
2017-01-11 14:09:48 +00:00
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
2017-01-04 14:31:53 +00:00
|
|
|
"k8s.io/apiserver/pkg/authentication/user"
|
2017-01-04 15:39:05 +00:00
|
|
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
2017-10-16 14:28:42 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/abac"
|
2015-11-20 06:14:49 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/abac/v0"
|
|
|
|
"k8s.io/kubernetes/pkg/apis/abac/v1beta1"
|
2014-10-06 23:11:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestEmptyFile(t *testing.T) {
|
|
|
|
_, err := newWithContents(t, "")
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unable to read policy file: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestOneLineFileNoNewLine(t *testing.T) {
|
2015-08-10 20:07:08 +00:00
|
|
|
_, err := newWithContents(t, `{"user":"scheduler", "readonly": true, "resource": "pods", "namespace":"ns1"}`)
|
2014-10-06 23:11:04 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unable to read policy file: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTwoLineFile(t *testing.T) {
|
2015-08-10 20:07:08 +00:00
|
|
|
_, err := newWithContents(t, `{"user":"scheduler", "readonly": true, "resource": "pods"}
|
|
|
|
{"user":"scheduler", "readonly": true, "resource": "services"}
|
2014-10-06 23:11:04 +00:00
|
|
|
`)
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unable to read policy file: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test the file that we will point users at as an example.
|
|
|
|
func TestExampleFile(t *testing.T) {
|
|
|
|
_, err := NewFromFile("./example_policy_file.jsonl")
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("unable to read policy file: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-20 06:14:49 +00:00
|
|
|
func TestAuthorizeV0(t *testing.T) {
|
2015-08-10 20:07:08 +00:00
|
|
|
a, err := newWithContents(t, `{ "readonly": true, "resource": "events" }
|
|
|
|
{"user":"scheduler", "readonly": true, "resource": "pods" }
|
|
|
|
{"user":"scheduler", "resource": "bindings" }
|
|
|
|
{"user":"kubelet", "readonly": true, "resource": "bindings" }
|
|
|
|
{"user":"kubelet", "resource": "events" }
|
|
|
|
{"user":"alice", "namespace": "projectCaribou"}
|
|
|
|
{"user":"bob", "readonly": true, "namespace": "projectCaribou"}
|
2014-10-06 23:11:04 +00:00
|
|
|
`)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to read policy file: %v", err)
|
|
|
|
}
|
|
|
|
|
2016-12-19 14:25:51 +00:00
|
|
|
authenticatedGroup := []string{user.AllAuthenticated}
|
|
|
|
|
|
|
|
uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup}
|
|
|
|
uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup}
|
|
|
|
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup}
|
2014-10-06 23:11:04 +00:00
|
|
|
|
|
|
|
testCases := []struct {
|
2017-09-29 21:21:40 +00:00
|
|
|
User user.DefaultInfo
|
|
|
|
Verb string
|
|
|
|
Resource string
|
|
|
|
NS string
|
|
|
|
APIGroup string
|
|
|
|
Path string
|
|
|
|
ExpectDecision authorizer.Decision
|
2014-10-06 23:11:04 +00:00
|
|
|
}{
|
|
|
|
// Scheduler can read pods
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uScheduler, Verb: "list", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2014-10-06 23:11:04 +00:00
|
|
|
// Scheduler cannot write pods
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uScheduler, Verb: "create", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
|
2014-10-06 23:11:04 +00:00
|
|
|
// Scheduler can write bindings
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uScheduler, Verb: "get", Resource: "bindings", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2014-10-06 23:11:04 +00:00
|
|
|
|
|
|
|
// Alice can read and write anything in the right namespace.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uAlice, Verb: "get", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "update", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "update", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "update", Resource: "foo", NS: "projectCaribou", APIGroup: "bar", ExpectDecision: authorizer.DecisionAllow},
|
2014-10-06 23:11:04 +00:00
|
|
|
// .. but not the wrong namespace.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uAlice, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "widgets", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
2014-10-06 23:11:04 +00:00
|
|
|
|
|
|
|
// Chuck can read events, since anyone can.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "get", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2014-10-06 23:11:04 +00:00
|
|
|
// Chuck can't do other things.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "update", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uChuck, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uChuck, Verb: "get", Resource: "floop", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
2014-10-06 23:11:04 +00:00
|
|
|
// Chunk can't access things with no kind or namespace
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
|
2014-10-06 23:11:04 +00:00
|
|
|
}
|
2015-08-10 20:07:08 +00:00
|
|
|
for i, tc := range testCases {
|
2014-10-06 23:11:04 +00:00
|
|
|
attr := authorizer.AttributesRecord{
|
|
|
|
User: &tc.User,
|
2015-09-29 01:11:51 +00:00
|
|
|
Verb: tc.Verb,
|
2015-01-29 19:14:54 +00:00
|
|
|
Resource: tc.Resource,
|
2014-10-06 23:11:04 +00:00
|
|
|
Namespace: tc.NS,
|
2015-11-20 06:14:49 +00:00
|
|
|
APIGroup: tc.APIGroup,
|
|
|
|
Path: tc.Path,
|
|
|
|
|
|
|
|
ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0,
|
2014-10-06 23:11:04 +00:00
|
|
|
}
|
2017-09-29 21:21:40 +00:00
|
|
|
decision, _, _ := a.Authorize(attr)
|
|
|
|
if tc.ExpectDecision != decision {
|
2015-11-20 06:14:49 +00:00
|
|
|
t.Logf("tc: %v -> attr %v", tc, attr)
|
2015-08-10 20:07:08 +00:00
|
|
|
t.Errorf("%d: Expected allowed=%v but actually allowed=%v\n\t%v",
|
2017-09-29 21:21:40 +00:00
|
|
|
i, tc.ExpectDecision, decision, tc)
|
2014-10-06 23:11:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-14 03:24:27 +00:00
|
|
|
func getResourceRules(infos []authorizer.ResourceRuleInfo) []authorizer.DefaultResourceRuleInfo {
|
|
|
|
rules := make([]authorizer.DefaultResourceRuleInfo, len(infos))
|
|
|
|
for i, info := range infos {
|
|
|
|
rules[i] = authorizer.DefaultResourceRuleInfo{
|
|
|
|
Verbs: info.GetVerbs(),
|
|
|
|
APIGroups: info.GetAPIGroups(),
|
|
|
|
Resources: info.GetResources(),
|
|
|
|
ResourceNames: info.GetResourceNames(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rules
|
|
|
|
}
|
|
|
|
|
|
|
|
func getNonResourceRules(infos []authorizer.NonResourceRuleInfo) []authorizer.DefaultNonResourceRuleInfo {
|
|
|
|
rules := make([]authorizer.DefaultNonResourceRuleInfo, len(infos))
|
|
|
|
for i, info := range infos {
|
|
|
|
rules[i] = authorizer.DefaultNonResourceRuleInfo{
|
|
|
|
Verbs: info.GetVerbs(),
|
|
|
|
NonResourceURLs: info.GetNonResourceURLs(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rules
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRulesFor(t *testing.T) {
|
|
|
|
a, err := newWithContents(t, `
|
|
|
|
{ "readonly": true, "resource": "events" }
|
|
|
|
{"user":"scheduler", "readonly": true, "resource": "pods" }
|
|
|
|
{"user":"scheduler", "resource": "bindings" }
|
|
|
|
{"user":"kubelet", "readonly": true, "resource": "pods" }
|
|
|
|
{"user":"kubelet", "resource": "events" }
|
|
|
|
{"user":"alice", "namespace": "projectCaribou"}
|
|
|
|
{"user":"bob", "readonly": true, "namespace": "projectCaribou"}
|
|
|
|
{"user":"bob", "readonly": true, "nonResourcePath": "*"}
|
|
|
|
{"group":"a", "resource": "bindings" }
|
|
|
|
{"group":"b", "readonly": true, "nonResourcePath": "*"}
|
|
|
|
`)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to read policy file: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
authenticatedGroup := []string{user.AllAuthenticated}
|
|
|
|
|
|
|
|
uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup}
|
|
|
|
uKubelet := user.DefaultInfo{Name: "kubelet", UID: "uid2", Groups: []string{"a", "b"}}
|
|
|
|
uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup}
|
|
|
|
uBob := user.DefaultInfo{Name: "bob", UID: "uid4", Groups: authenticatedGroup}
|
|
|
|
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: []string{"a", "b"}}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
User user.DefaultInfo
|
|
|
|
Namespace string
|
|
|
|
ExpectResourceRules []authorizer.DefaultResourceRuleInfo
|
|
|
|
ExpectNonResourceRules []authorizer.DefaultNonResourceRuleInfo
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
User: uScheduler,
|
|
|
|
Namespace: "ns1",
|
|
|
|
ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"events"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"pods"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"*"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"bindings"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
User: uKubelet,
|
|
|
|
Namespace: "ns1",
|
|
|
|
ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"pods"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"*"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"events"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"*"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"bindings"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"*"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
NonResourceURLs: []string{"*"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
User: uAlice,
|
|
|
|
Namespace: "projectCaribou",
|
|
|
|
ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"events"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"*"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"*"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
User: uBob,
|
|
|
|
Namespace: "projectCaribou",
|
|
|
|
ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"events"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"*"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"*"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
NonResourceURLs: []string{"*"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
User: uChuck,
|
|
|
|
Namespace: "ns1",
|
|
|
|
ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"*"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"bindings"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
APIGroups: []string{"*"},
|
|
|
|
Resources: []string{"*"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{
|
|
|
|
{
|
|
|
|
Verbs: []string{"get", "list", "watch"},
|
|
|
|
NonResourceURLs: []string{"*"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, tc := range testCases {
|
|
|
|
attr := authorizer.AttributesRecord{
|
|
|
|
User: &tc.User,
|
|
|
|
Namespace: tc.Namespace,
|
|
|
|
}
|
|
|
|
resourceRules, nonResourceRules, _, _ := a.RulesFor(attr.GetUser(), attr.GetNamespace())
|
|
|
|
actualResourceRules := getResourceRules(resourceRules)
|
|
|
|
if !reflect.DeepEqual(tc.ExpectResourceRules, actualResourceRules) {
|
|
|
|
t.Logf("tc: %v -> attr %v", tc, attr)
|
|
|
|
t.Errorf("%d: Expected: \n%#v\n but actual: \n%#v\n",
|
|
|
|
i, tc.ExpectResourceRules, actualResourceRules)
|
|
|
|
}
|
|
|
|
actualNonResourceRules := getNonResourceRules(nonResourceRules)
|
|
|
|
if !reflect.DeepEqual(tc.ExpectNonResourceRules, actualNonResourceRules) {
|
|
|
|
t.Logf("tc: %v -> attr %v", tc, attr)
|
|
|
|
t.Errorf("%d: Expected: \n%#v\n but actual: \n%#v\n",
|
|
|
|
i, tc.ExpectNonResourceRules, actualNonResourceRules)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-20 06:14:49 +00:00
|
|
|
func TestAuthorizeV1beta1(t *testing.T) {
|
|
|
|
a, err := newWithContents(t,
|
|
|
|
`
|
|
|
|
# Comment line, after a blank line
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "readonly": true, "nonResourcePath": "/api"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "nonResourcePath": "/custom"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "nonResourcePath": "/root/*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"noresource", "nonResourcePath": "*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "readonly": true, "resource": "events", "namespace": "*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"scheduler", "readonly": true, "resource": "pods", "namespace": "*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"scheduler", "resource": "bindings", "namespace": "*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"kubelet", "readonly": true, "resource": "bindings", "namespace": "*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"kubelet", "resource": "events", "namespace": "*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"alice", "resource": "*", "namespace": "projectCaribou"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"bob", "readonly": true, "resource": "*", "namespace": "projectCaribou"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"debbie", "resource": "pods", "namespace": "projectCaribou"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectAnyGroup", "apiGroup": "*"}}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectEmptyGroup", "apiGroup": "" }}
|
|
|
|
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectXGroup", "apiGroup": "x"}}`)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unable to read policy file: %v", err)
|
|
|
|
}
|
|
|
|
|
2016-12-19 14:25:51 +00:00
|
|
|
authenticatedGroup := []string{user.AllAuthenticated}
|
|
|
|
|
|
|
|
uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup}
|
|
|
|
uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup}
|
|
|
|
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup}
|
|
|
|
uDebbie := user.DefaultInfo{Name: "debbie", UID: "uid6", Groups: authenticatedGroup}
|
|
|
|
uNoResource := user.DefaultInfo{Name: "noresource", UID: "uid7", Groups: authenticatedGroup}
|
|
|
|
uAPIGroup := user.DefaultInfo{Name: "apigroupuser", UID: "uid8", Groups: authenticatedGroup}
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
testCases := []struct {
|
2017-09-29 21:21:40 +00:00
|
|
|
User user.DefaultInfo
|
|
|
|
Verb string
|
|
|
|
Resource string
|
|
|
|
APIGroup string
|
|
|
|
NS string
|
|
|
|
Path string
|
|
|
|
ExpectDecision authorizer.Decision
|
2015-11-20 06:14:49 +00:00
|
|
|
}{
|
|
|
|
// Scheduler can read pods
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uScheduler, Verb: "list", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
// Scheduler cannot write pods
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uScheduler, Verb: "create", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
|
2015-11-20 06:14:49 +00:00
|
|
|
// Scheduler can write bindings
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uScheduler, Verb: "get", Resource: "bindings", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
// Alice can read and write anything in the right namespace.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uAlice, Verb: "get", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "update", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAlice, Verb: "update", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
// .. but not the wrong namespace.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uAlice, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "widgets", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uAlice, Verb: "get", Resource: "", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
// Debbie can write to pods in the right namespace
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uDebbie, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
// Chuck can read events, since anyone can.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "get", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
// Chuck can't do other things.
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "update", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uChuck, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uChuck, Verb: "get", Resource: "floop", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
|
2015-11-20 06:14:49 +00:00
|
|
|
// Chuck can't access things with no resource or namespace
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
|
2015-11-20 06:14:49 +00:00
|
|
|
// but can access /api
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "get", Path: "/api", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
// though he cannot write to it
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "create", Path: "/api", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
|
2015-11-20 06:14:49 +00:00
|
|
|
// while he can write to /custom
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "update", Path: "/custom", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
// he cannot get "/root"
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "get", Path: "/root", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
|
2015-11-20 06:14:49 +00:00
|
|
|
// but can get any subpath
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uChuck, Verb: "get", Path: "/root/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uChuck, Verb: "get", Path: "/root/test/1/2/3", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
// the user "noresource" can get any non-resource request
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uNoResource, Verb: "get", Path: "", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uNoResource, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uNoResource, Verb: "get", Path: "/foo/bar/baz", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
// but cannot get any request where IsResourceRequest() == true
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uNoResource, Verb: "get", Path: "/", Resource: "", NS: "bar", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uNoResource, Verb: "get", Path: "/foo/bar/baz", Resource: "foo", NS: "bar", ExpectDecision: authorizer.DecisionNoOpinion},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
// Test APIGroup matching
|
2017-09-29 21:21:40 +00:00
|
|
|
{User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectAnyGroup", ExpectDecision: authorizer.DecisionAllow},
|
|
|
|
{User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectEmptyGroup", ExpectDecision: authorizer.DecisionNoOpinion},
|
|
|
|
{User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectXGroup", ExpectDecision: authorizer.DecisionAllow},
|
2015-11-20 06:14:49 +00:00
|
|
|
}
|
|
|
|
for i, tc := range testCases {
|
|
|
|
attr := authorizer.AttributesRecord{
|
|
|
|
User: &tc.User,
|
|
|
|
Verb: tc.Verb,
|
|
|
|
Resource: tc.Resource,
|
|
|
|
APIGroup: tc.APIGroup,
|
|
|
|
Namespace: tc.NS,
|
|
|
|
ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0,
|
|
|
|
Path: tc.Path,
|
|
|
|
}
|
|
|
|
// t.Logf("tc %2v: %v -> attr %v", i, tc, attr)
|
2017-09-29 21:21:40 +00:00
|
|
|
decision, _, _ := a.Authorize(attr)
|
|
|
|
if tc.ExpectDecision != decision {
|
2015-11-20 06:14:49 +00:00
|
|
|
t.Errorf("%d: Expected allowed=%v but actually allowed=%v, for case %+v & %+v",
|
2017-09-29 21:21:40 +00:00
|
|
|
i, tc.ExpectDecision, decision, tc, attr)
|
2015-11-20 06:14:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-16 15:20:05 +00:00
|
|
|
func TestSubjectMatches(t *testing.T) {
|
|
|
|
testCases := map[string]struct {
|
|
|
|
User user.DefaultInfo
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy runtime.Object
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch bool
|
|
|
|
}{
|
2016-12-19 14:25:51 +00:00
|
|
|
"v0 empty policy does not match unauthed user": {
|
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "",
|
|
|
|
},
|
2016-12-19 14:25:51 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 * user policy does not match unauthed user": {
|
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "*",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 * group policy does not match unauthed user": {
|
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "*",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
"v0 empty policy matches authed user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
|
|
|
"v0 empty policy matches authed user with groups": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"v0 user policy does not match unauthed user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 user policy does not match different user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 user policy is case-sensitive": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 user policy does not match substring": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 user policy matches username": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
"v0 group policy does not match unauthed user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "Foo",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 group policy does not match user in different group": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "A",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 group policy is case-sensitive": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "b",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 group policy does not match substring": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "B",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 group policy matches user in group": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "",
|
|
|
|
Group: "B",
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
"v0 user and group policy requires user match": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "B",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 user and group policy requires group match": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "D",
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v0 user and group policy matches": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v0.Policy{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "B",
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
|
|
|
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 empty policy does not match unauthed user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2016-12-19 14:25:51 +00:00
|
|
|
"v1 * user policy does not match unauthed user": {
|
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v1 * group policy does not match unauthed user": {
|
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "*",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 empty policy does not match authed user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 empty policy does not match authed user with groups": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
"v1 user policy does not match unauthed user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 user policy does not match different user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v1 user policy is case-sensitive": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v1 user policy does not match substring": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
|
|
|
"v1 user policy matches username": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
|
|
|
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 group policy does not match unauthed user": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "Foo",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 group policy does not match user in different group": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "A",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 group policy is case-sensitive": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "b",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 group policy does not match substring": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "B",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 group policy matches user in group": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "",
|
|
|
|
Group: "B",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
|
|
|
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 user and group policy requires user match": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "B",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 user and group policy requires group match": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "D",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: false,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
"v1 user and group policy matches": {
|
2016-12-19 14:25:51 +00:00
|
|
|
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
2015-11-20 06:14:49 +00:00
|
|
|
Policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "Foo",
|
|
|
|
Group: "B",
|
|
|
|
},
|
|
|
|
},
|
2014-12-16 15:20:05 +00:00
|
|
|
ExpectMatch: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, tc := range testCases {
|
2017-10-16 14:28:42 +00:00
|
|
|
policy := &abac.Policy{}
|
|
|
|
if err := abac.Scheme.Convert(tc.Policy, policy, nil); err != nil {
|
2015-11-20 06:14:49 +00:00
|
|
|
t.Errorf("%s: error converting: %v", k, err)
|
|
|
|
continue
|
|
|
|
}
|
2014-12-16 15:20:05 +00:00
|
|
|
attr := authorizer.AttributesRecord{
|
|
|
|
User: &tc.User,
|
|
|
|
}
|
2017-07-14 03:24:27 +00:00
|
|
|
actualMatch := subjectMatches(*policy, attr.GetUser())
|
2014-12-16 15:20:05 +00:00
|
|
|
if tc.ExpectMatch != actualMatch {
|
|
|
|
t.Errorf("%v: Expected actorMatches=%v but actually got=%v",
|
|
|
|
k, tc.ExpectMatch, actualMatch)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-14 03:24:27 +00:00
|
|
|
func newWithContents(t *testing.T, contents string) (policyList, error) {
|
2014-10-06 23:11:04 +00:00
|
|
|
f, err := ioutil.TempFile("", "abac_test")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error creating policyfile: %v", err)
|
|
|
|
}
|
|
|
|
f.Close()
|
|
|
|
defer os.Remove(f.Name())
|
|
|
|
|
|
|
|
if err := ioutil.WriteFile(f.Name(), []byte(contents), 0700); err != nil {
|
|
|
|
t.Fatalf("unexpected error writing policyfile: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
pl, err := NewFromFile(f.Name())
|
|
|
|
return pl, err
|
|
|
|
}
|
2015-03-07 10:00:45 +00:00
|
|
|
|
|
|
|
func TestPolicy(t *testing.T) {
|
|
|
|
tests := []struct {
|
2015-11-20 06:14:49 +00:00
|
|
|
policy runtime.Object
|
2015-03-07 10:00:45 +00:00
|
|
|
attr authorizer.Attributes
|
|
|
|
matches bool
|
|
|
|
name string
|
|
|
|
}{
|
2015-11-20 06:14:49 +00:00
|
|
|
// v0 mismatches
|
2015-03-07 10:00:45 +00:00
|
|
|
{
|
2015-11-20 06:14:49 +00:00
|
|
|
policy: &v0.Policy{
|
2015-03-07 10:00:45 +00:00
|
|
|
Readonly: true,
|
|
|
|
},
|
2016-12-19 14:25:51 +00:00
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
|
|
|
Verb: "create",
|
|
|
|
},
|
2015-03-07 10:00:45 +00:00
|
|
|
matches: false,
|
2015-11-20 06:14:49 +00:00
|
|
|
name: "v0 read-only mismatch",
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
{
|
2015-11-20 06:14:49 +00:00
|
|
|
policy: &v0.Policy{
|
2015-03-07 10:00:45 +00:00
|
|
|
User: "foo",
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
2016-12-19 14:25:51 +00:00
|
|
|
Name: "bar",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
matches: false,
|
2015-11-20 06:14:49 +00:00
|
|
|
name: "v0 user name mis-match",
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
{
|
2015-11-20 06:14:49 +00:00
|
|
|
policy: &v0.Policy{
|
2015-03-07 10:00:45 +00:00
|
|
|
Resource: "foo",
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Resource: "bar",
|
|
|
|
ResourceRequest: true,
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
matches: false,
|
2015-11-20 06:14:49 +00:00
|
|
|
name: "v0 resource mis-match",
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
{
|
2015-11-20 06:14:49 +00:00
|
|
|
policy: &v0.Policy{
|
2015-03-07 10:00:45 +00:00
|
|
|
User: "foo",
|
|
|
|
Resource: "foo",
|
|
|
|
Namespace: "foo",
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
2016-12-19 14:25:51 +00:00
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Resource: "foo",
|
|
|
|
Namespace: "foo",
|
|
|
|
ResourceRequest: true,
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
matches: true,
|
2015-11-20 06:14:49 +00:00
|
|
|
name: "v0 namespace mis-match",
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
|
|
|
|
// v0 matches
|
2015-03-07 10:00:45 +00:00
|
|
|
{
|
2016-12-19 14:25:51 +00:00
|
|
|
policy: &v0.Policy{},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
matches: true,
|
|
|
|
name: "v0 null resource",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v0.Policy{
|
|
|
|
Readonly: true,
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Verb: "get",
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v0 read-only match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v0.Policy{
|
|
|
|
User: "foo",
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
2016-12-19 14:25:51 +00:00
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v0 user name match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v0.Policy{
|
|
|
|
Resource: "foo",
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Resource: "foo",
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v0 resource match",
|
|
|
|
},
|
|
|
|
|
|
|
|
// v1 mismatches
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
ResourceRequest: true,
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
matches: false,
|
2015-11-20 06:14:49 +00:00
|
|
|
name: "v1 null",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
2016-12-19 14:25:51 +00:00
|
|
|
Name: "bar",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: false,
|
|
|
|
name: "v1 user name mis-match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
Readonly: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: false,
|
|
|
|
name: "v1 read-only mismatch",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
Resource: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Resource: "bar",
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: false,
|
|
|
|
name: "v1 resource mis-match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "foo",
|
|
|
|
Namespace: "barr",
|
|
|
|
Resource: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
2016-12-19 14:25:51 +00:00
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
Namespace: "bar",
|
|
|
|
Resource: "baz",
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: false,
|
|
|
|
name: "v1 namespace mis-match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
NonResourcePath: "/api",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Path: "/api2",
|
|
|
|
ResourceRequest: false,
|
|
|
|
},
|
|
|
|
matches: false,
|
|
|
|
name: "v1 non-resource mis-match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
NonResourcePath: "/api/*",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Path: "/api2/foo",
|
|
|
|
ResourceRequest: false,
|
|
|
|
},
|
|
|
|
matches: false,
|
|
|
|
name: "v1 non-resource wildcard subpath mis-match",
|
|
|
|
},
|
|
|
|
|
|
|
|
// v1 matches
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
2016-12-19 14:25:51 +00:00
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 user match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 user wildcard match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
Group: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
2016-12-19 14:25:51 +00:00
|
|
|
Groups: []string{"bar", user.AllAuthenticated},
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 group match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
Group: "*",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
2016-12-19 14:25:51 +00:00
|
|
|
Groups: []string{"bar", user.AllAuthenticated},
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 group wildcard match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
Readonly: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Verb: "get",
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 read-only match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
Resource: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Resource: "foo",
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 resource match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "foo",
|
|
|
|
Namespace: "bar",
|
|
|
|
Resource: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
|
|
|
User: &user.DefaultInfo{
|
2016-12-19 14:25:51 +00:00
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
2015-11-20 06:14:49 +00:00
|
|
|
},
|
|
|
|
Namespace: "bar",
|
|
|
|
Resource: "baz",
|
|
|
|
ResourceRequest: true,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 namespace match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
NonResourcePath: "/api",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Path: "/api",
|
|
|
|
ResourceRequest: false,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 non-resource match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
NonResourcePath: "*",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Path: "/api",
|
|
|
|
ResourceRequest: false,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 non-resource wildcard match",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
policy: &v1beta1.Policy{
|
|
|
|
Spec: v1beta1.PolicySpec{
|
|
|
|
User: "*",
|
|
|
|
NonResourcePath: "/api/*",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
attr: authorizer.AttributesRecord{
|
2016-12-19 14:25:51 +00:00
|
|
|
User: &user.DefaultInfo{
|
|
|
|
Name: "foo",
|
|
|
|
Groups: []string{user.AllAuthenticated},
|
|
|
|
},
|
2015-11-20 06:14:49 +00:00
|
|
|
Path: "/api/foo",
|
|
|
|
ResourceRequest: false,
|
|
|
|
},
|
|
|
|
matches: true,
|
|
|
|
name: "v1 non-resource wildcard subpath match",
|
2015-03-07 10:00:45 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
2017-10-16 14:28:42 +00:00
|
|
|
policy := &abac.Policy{}
|
|
|
|
if err := abac.Scheme.Convert(test.policy, policy, nil); err != nil {
|
2015-11-20 06:14:49 +00:00
|
|
|
t.Errorf("%s: error converting: %v", test.name, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
matches := matches(*policy, test.attr)
|
2015-03-07 10:00:45 +00:00
|
|
|
if test.matches != matches {
|
2015-11-20 06:14:49 +00:00
|
|
|
t.Errorf("%s: expected: %t, saw: %t", test.name, test.matches, matches)
|
|
|
|
continue
|
2015-03-07 10:00:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|