1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270 |
- /*
- Copyright 2014 The Kubernetes Authors.
- 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 (
- "context"
- "io/ioutil"
- "os"
- "reflect"
- "testing"
- "k8s.io/apimachinery/pkg/runtime"
- "k8s.io/apiserver/pkg/authentication/user"
- "k8s.io/apiserver/pkg/authorization/authorizer"
- "k8s.io/kubernetes/pkg/apis/abac"
- "k8s.io/kubernetes/pkg/apis/abac/v0"
- "k8s.io/kubernetes/pkg/apis/abac/v1beta1"
- )
- 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) {
- _, err := newWithContents(t, `{"user":"scheduler", "readonly": true, "resource": "pods", "namespace":"ns1"}`)
- if err != nil {
- t.Errorf("unable to read policy file: %v", err)
- }
- }
- func TestTwoLineFile(t *testing.T) {
- _, err := newWithContents(t, `{"user":"scheduler", "readonly": true, "resource": "pods"}
- {"user":"scheduler", "readonly": true, "resource": "services"}
- `)
- 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)
- }
- }
- func TestAuthorizeV0(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": "bindings" }
- {"user":"kubelet", "resource": "events" }
- {"user":"alice", "namespace": "projectCaribou"}
- {"user":"bob", "readonly": true, "namespace": "projectCaribou"}
- `)
- 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}
- uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup}
- uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup}
- testCases := []struct {
- User user.DefaultInfo
- Verb string
- Resource string
- NS string
- APIGroup string
- Path string
- ExpectDecision authorizer.Decision
- }{
- // Scheduler can read pods
- {User: uScheduler, Verb: "list", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
- {User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // Scheduler cannot write pods
- {User: uScheduler, Verb: "create", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
- {User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
- // Scheduler can write bindings
- {User: uScheduler, Verb: "get", Resource: "bindings", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
- {User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // Alice can read and write anything in the right namespace.
- {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},
- // .. but not the wrong namespace.
- {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},
- // Chuck can read events, since anyone can.
- {User: uChuck, Verb: "get", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
- {User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // Chuck can't do other things.
- {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},
- // Chunk can't access things with no kind or namespace
- {User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
- }
- for i, tc := range testCases {
- attr := authorizer.AttributesRecord{
- User: &tc.User,
- Verb: tc.Verb,
- Resource: tc.Resource,
- Namespace: tc.NS,
- APIGroup: tc.APIGroup,
- Path: tc.Path,
- ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0,
- }
- decision, _, _ := a.Authorize(context.Background(), attr)
- if tc.ExpectDecision != decision {
- t.Logf("tc: %v -> attr %v", tc, attr)
- t.Errorf("%d: Expected allowed=%v but actually allowed=%v\n\t%v",
- i, tc.ExpectDecision, decision, tc)
- }
- }
- }
- 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)
- }
- }
- }
- 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)
- }
- 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}
- testCases := []struct {
- User user.DefaultInfo
- Verb string
- Resource string
- APIGroup string
- NS string
- Path string
- ExpectDecision authorizer.Decision
- }{
- // Scheduler can read pods
- {User: uScheduler, Verb: "list", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
- {User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // Scheduler cannot write pods
- {User: uScheduler, Verb: "create", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion},
- {User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
- // Scheduler can write bindings
- {User: uScheduler, Verb: "get", Resource: "bindings", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
- {User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // Alice can read and write anything in the right namespace.
- {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},
- // .. but not the wrong namespace.
- {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},
- // Debbie can write to pods in the right namespace
- {User: uDebbie, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow},
- // Chuck can read events, since anyone can.
- {User: uChuck, Verb: "get", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionAllow},
- {User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // Chuck can't do other things.
- {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},
- // Chuck can't access things with no resource or namespace
- {User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
- // but can access /api
- {User: uChuck, Verb: "get", Path: "/api", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // though he cannot write to it
- {User: uChuck, Verb: "create", Path: "/api", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
- // while he can write to /custom
- {User: uChuck, Verb: "update", Path: "/custom", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
- // he cannot get "/root"
- {User: uChuck, Verb: "get", Path: "/root", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
- // but can get any subpath
- {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},
- // the user "noresource" can get any non-resource request
- {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},
- // but cannot get any request where IsResourceRequest() == true
- {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},
- // Test APIGroup matching
- {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},
- }
- 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)
- decision, _, _ := a.Authorize(context.Background(), attr)
- if tc.ExpectDecision != decision {
- t.Errorf("%d: Expected allowed=%v but actually allowed=%v, for case %+v & %+v",
- i, tc.ExpectDecision, decision, tc, attr)
- }
- }
- }
- func TestSubjectMatches(t *testing.T) {
- testCases := map[string]struct {
- User user.DefaultInfo
- Policy runtime.Object
- ExpectMatch bool
- }{
- "v0 empty policy does not match unauthed user": {
- User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
- Policy: &v0.Policy{
- User: "",
- Group: "",
- },
- 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,
- },
- "v0 empty policy matches authed user": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "",
- Group: "",
- },
- ExpectMatch: true,
- },
- "v0 empty policy matches authed user with groups": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "",
- Group: "",
- },
- ExpectMatch: true,
- },
- "v0 user policy does not match unauthed user": {
- User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "",
- },
- ExpectMatch: false,
- },
- "v0 user policy does not match different user": {
- User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "",
- },
- ExpectMatch: false,
- },
- "v0 user policy is case-sensitive": {
- User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "",
- },
- ExpectMatch: false,
- },
- "v0 user policy does not match substring": {
- User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "",
- },
- ExpectMatch: false,
- },
- "v0 user policy matches username": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "",
- },
- ExpectMatch: true,
- },
- "v0 group policy does not match unauthed user": {
- User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
- Policy: &v0.Policy{
- User: "",
- Group: "Foo",
- },
- ExpectMatch: false,
- },
- "v0 group policy does not match user in different group": {
- User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "",
- Group: "A",
- },
- ExpectMatch: false,
- },
- "v0 group policy is case-sensitive": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "",
- Group: "b",
- },
- ExpectMatch: false,
- },
- "v0 group policy does not match substring": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "",
- Group: "B",
- },
- ExpectMatch: false,
- },
- "v0 group policy matches user in group": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "",
- Group: "B",
- },
- ExpectMatch: true,
- },
- "v0 user and group policy requires user match": {
- User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "B",
- },
- ExpectMatch: false,
- },
- "v0 user and group policy requires group match": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "D",
- },
- ExpectMatch: false,
- },
- "v0 user and group policy matches": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v0.Policy{
- User: "Foo",
- Group: "B",
- },
- ExpectMatch: true,
- },
- "v1 empty 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 * 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,
- },
- "v1 empty policy does not match authed user": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "",
- Group: "",
- },
- },
- ExpectMatch: false,
- },
- "v1 empty policy does not match authed user with groups": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "",
- Group: "",
- },
- },
- ExpectMatch: false,
- },
- "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: "Foo",
- Group: "",
- },
- },
- ExpectMatch: false,
- },
- "v1 user policy does not match different user": {
- User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "Foo",
- Group: "",
- },
- },
- ExpectMatch: false,
- },
- "v1 user policy is case-sensitive": {
- User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "Foo",
- Group: "",
- },
- },
- ExpectMatch: false,
- },
- "v1 user policy does not match substring": {
- User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "Foo",
- Group: "",
- },
- },
- ExpectMatch: false,
- },
- "v1 user policy matches username": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "Foo",
- Group: "",
- },
- },
- ExpectMatch: true,
- },
- "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: "Foo",
- },
- },
- ExpectMatch: false,
- },
- "v1 group policy does not match user in different group": {
- User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "",
- Group: "A",
- },
- },
- ExpectMatch: false,
- },
- "v1 group policy is case-sensitive": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "",
- Group: "b",
- },
- },
- ExpectMatch: false,
- },
- "v1 group policy does not match substring": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "",
- Group: "B",
- },
- },
- ExpectMatch: false,
- },
- "v1 group policy matches user in group": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "",
- Group: "B",
- },
- },
- ExpectMatch: true,
- },
- "v1 user and group policy requires user match": {
- User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "Foo",
- Group: "B",
- },
- },
- ExpectMatch: false,
- },
- "v1 user and group policy requires group match": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "Foo",
- Group: "D",
- },
- },
- ExpectMatch: false,
- },
- "v1 user and group policy matches": {
- User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
- Policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "Foo",
- Group: "B",
- },
- },
- ExpectMatch: true,
- },
- }
- for k, tc := range testCases {
- policy := &abac.Policy{}
- if err := abac.Scheme.Convert(tc.Policy, policy, nil); err != nil {
- t.Errorf("%s: error converting: %v", k, err)
- continue
- }
- attr := authorizer.AttributesRecord{
- User: &tc.User,
- }
- actualMatch := subjectMatches(*policy, attr.GetUser())
- if tc.ExpectMatch != actualMatch {
- t.Errorf("%v: Expected actorMatches=%v but actually got=%v",
- k, tc.ExpectMatch, actualMatch)
- }
- }
- }
- func newWithContents(t *testing.T, contents string) (PolicyList, error) {
- 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
- }
- func TestPolicy(t *testing.T) {
- tests := []struct {
- policy runtime.Object
- attr authorizer.Attributes
- matches bool
- name string
- }{
- // v0 mismatches
- {
- policy: &v0.Policy{
- Readonly: true,
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Verb: "create",
- },
- matches: false,
- name: "v0 read-only mismatch",
- },
- {
- policy: &v0.Policy{
- User: "foo",
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "bar",
- Groups: []string{user.AllAuthenticated},
- },
- },
- matches: false,
- name: "v0 user name mis-match",
- },
- {
- policy: &v0.Policy{
- Resource: "foo",
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Resource: "bar",
- ResourceRequest: true,
- },
- matches: false,
- name: "v0 resource mis-match",
- },
- {
- policy: &v0.Policy{
- User: "foo",
- Resource: "foo",
- Namespace: "foo",
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Resource: "foo",
- Namespace: "foo",
- ResourceRequest: true,
- },
- matches: true,
- name: "v0 namespace mis-match",
- },
- // v0 matches
- {
- policy: &v0.Policy{},
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- ResourceRequest: true,
- },
- matches: true,
- name: "v0 null resource",
- },
- {
- policy: &v0.Policy{
- Readonly: true,
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Verb: "get",
- },
- matches: true,
- name: "v0 read-only match",
- },
- {
- policy: &v0.Policy{
- User: "foo",
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- },
- matches: true,
- name: "v0 user name match",
- },
- {
- policy: &v0.Policy{
- Resource: "foo",
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Resource: "foo",
- ResourceRequest: true,
- },
- matches: true,
- name: "v0 resource match",
- },
- // v1 mismatches
- {
- policy: &v1beta1.Policy{},
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- ResourceRequest: true,
- },
- matches: false,
- name: "v1 null",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "foo",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "bar",
- Groups: []string{user.AllAuthenticated},
- },
- ResourceRequest: true,
- },
- matches: false,
- name: "v1 user name mis-match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- Readonly: true,
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- ResourceRequest: true,
- },
- matches: false,
- name: "v1 read-only mismatch",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- Resource: "foo",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- 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{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- 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{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Path: "/api2",
- ResourceRequest: false,
- },
- matches: false,
- name: "v1 non-resource mis-match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- NonResourcePath: "/api/*",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- 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{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- ResourceRequest: true,
- },
- matches: true,
- name: "v1 user match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- 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",
- Groups: []string{"bar", user.AllAuthenticated},
- },
- ResourceRequest: true,
- },
- matches: true,
- name: "v1 group match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- Group: "*",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{"bar", user.AllAuthenticated},
- },
- ResourceRequest: true,
- },
- matches: true,
- name: "v1 group wildcard match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- Readonly: true,
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Verb: "get",
- ResourceRequest: true,
- },
- matches: true,
- name: "v1 read-only match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- Resource: "foo",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- 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{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Namespace: "bar",
- Resource: "baz",
- ResourceRequest: true,
- },
- matches: true,
- name: "v1 namespace match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- NonResourcePath: "/api",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Path: "/api",
- ResourceRequest: false,
- },
- matches: true,
- name: "v1 non-resource match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- NonResourcePath: "*",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Path: "/api",
- ResourceRequest: false,
- },
- matches: true,
- name: "v1 non-resource wildcard match",
- },
- {
- policy: &v1beta1.Policy{
- Spec: v1beta1.PolicySpec{
- User: "*",
- NonResourcePath: "/api/*",
- },
- },
- attr: authorizer.AttributesRecord{
- User: &user.DefaultInfo{
- Name: "foo",
- Groups: []string{user.AllAuthenticated},
- },
- Path: "/api/foo",
- ResourceRequest: false,
- },
- matches: true,
- name: "v1 non-resource wildcard subpath match",
- },
- }
- for _, test := range tests {
- policy := &abac.Policy{}
- if err := abac.Scheme.Convert(test.policy, policy, nil); err != nil {
- t.Errorf("%s: error converting: %v", test.name, err)
- continue
- }
- matches := matches(*policy, test.attr)
- if test.matches != matches {
- t.Errorf("%s: expected: %t, saw: %t", test.name, test.matches, matches)
- continue
- }
- }
- }
|