package authorizer import ( "strings" "testing" kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/auth/user" authorizationapi "github.com/openshift/origin/pkg/authorization/api" testpolicyregistry "github.com/openshift/origin/pkg/authorization/registry/test" ) const testMasterNamespace = "master" type authorizeTest struct { globalPolicy []authorizationapi.Policy namespacedPolicy []authorizationapi.Policy policyRetrievalError error globalPolicyBinding []authorizationapi.PolicyBinding namespacedPolicyBinding []authorizationapi.PolicyBinding policyBindingRetrievalError error attributes *openshiftAuthorizationAttributes expectedAllowed bool expectedReason string expectedError string } func TestAdminEditingGlobalDeploymentConfig(t *testing.T) { test := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "ClusterAdmin", }, verb: "update", resource: "deploymentConfigs", namespace: testMasterNamespace, }, expectedAllowed: true, expectedReason: "allowed by rule in master", } test.globalPolicy, test.globalPolicyBinding = newDefaultGlobalPolicy() test.test(t) } func TestDisallowedViewingGlobalPods(t *testing.T) { test := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "SomeYahoo", }, verb: "get", resource: "pods", namespace: testMasterNamespace, }, expectedAllowed: false, expectedReason: "denied by default", } test.globalPolicy, test.globalPolicyBinding = newDefaultGlobalPolicy() test.test(t) } func TestProjectAdminEditPolicy(t *testing.T) { test := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Anna", }, verb: "update", resource: "roles", namespace: "adze", }, expectedAllowed: true, expectedReason: "allowed by rule in adze", } test.globalPolicy, test.globalPolicyBinding = newDefaultGlobalPolicy() test.namespacedPolicy, test.namespacedPolicyBinding = newAdzePolicy() test.test(t) } func TestGlobalPolicyOutranksLocalPolicy(t *testing.T) { test := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "ClusterAdmin", }, verb: "update", resource: "roles", namespace: "adze", }, expectedAllowed: true, expectedReason: "allowed by rule in master", } test.globalPolicy, test.globalPolicyBinding = newDefaultGlobalPolicy() test.namespacedPolicy, test.namespacedPolicyBinding = newAdzePolicy() test.test(t) } func TestResourceKindRestrictionsWork(t *testing.T) { test1 := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Rachel", }, verb: "get", resource: "buildConfigs", namespace: "adze", }, expectedAllowed: true, expectedReason: "allowed by rule in adze", } test1.globalPolicy, test1.globalPolicyBinding = newDefaultGlobalPolicy() test1.namespacedPolicy, test1.namespacedPolicyBinding = newAdzePolicy() test1.test(t) test2 := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Rachel", }, verb: "get", resource: "pods", namespace: "adze", }, expectedAllowed: false, expectedReason: "denied by default", } test2.globalPolicy, test2.globalPolicyBinding = newDefaultGlobalPolicy() test2.namespacedPolicy, test2.namespacedPolicyBinding = newAdzePolicy() test2.test(t) } func TestResourceKindRestrictionsWithWeirdWork(t *testing.T) { test1 := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Rachel", }, verb: "get", resource: "BUILDCONFIGS", namespace: "adze", }, expectedAllowed: true, expectedReason: "allowed by rule in adze", } test1.globalPolicy, test1.globalPolicyBinding = newDefaultGlobalPolicy() test1.namespacedPolicy, test1.namespacedPolicyBinding = newAdzePolicy() test1.test(t) test2 := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Rachel", }, verb: "get", resource: "buildconfigs", namespace: "adze", }, expectedAllowed: true, expectedReason: "allowed by rule in adze", } test2.globalPolicy, test2.globalPolicyBinding = newDefaultGlobalPolicy() test2.namespacedPolicy, test2.namespacedPolicyBinding = newAdzePolicy() test2.test(t) } func TestLocalRightsDoNotGrantGlobalRights(t *testing.T) { test := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Rachel", }, verb: "get", resource: "buildConfigs", namespace: "backsaw", }, expectedAllowed: false, expectedReason: "denied by default", } test.globalPolicy, test.globalPolicyBinding = newDefaultGlobalPolicy() test.namespacedPolicy, test.namespacedPolicyBinding = newAdzePolicy() test.test(t) } func TestVerbRestrictionsWork(t *testing.T) { test1 := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Valerie", }, verb: "get", resource: "buildConfigs", namespace: "adze", }, expectedAllowed: true, expectedReason: "allowed by rule in adze", } test1.globalPolicy, test1.globalPolicyBinding = newDefaultGlobalPolicy() test1.namespacedPolicy, test1.namespacedPolicyBinding = newAdzePolicy() test1.test(t) test2 := &authorizeTest{ attributes: &openshiftAuthorizationAttributes{ user: &user.DefaultInfo{ Name: "Valerie", }, verb: "create", resource: "buildConfigs", namespace: "adze", }, expectedAllowed: false, expectedReason: "denied by default", } test2.globalPolicy, test2.globalPolicyBinding = newDefaultGlobalPolicy() test2.namespacedPolicy, test2.namespacedPolicyBinding = newAdzePolicy() test2.test(t) } func (test *authorizeTest) test(t *testing.T) { policies := make([]authorizationapi.Policy, 0, 0) policies = append(policies, test.namespacedPolicy...) policies = append(policies, test.globalPolicy...) policyRegistry := &testpolicyregistry.PolicyRegistry{ Err: test.policyRetrievalError, MasterNamespace: testMasterNamespace, Policies: policies, } policyBindings := make([]authorizationapi.PolicyBinding, 0, 0) policyBindings = append(policyBindings, test.namespacedPolicyBinding...) policyBindings = append(policyBindings, test.globalPolicyBinding...) policyBindingRegistry := &testpolicyregistry.PolicyBindingRegistry{ Err: test.policyBindingRetrievalError, MasterNamespace: testMasterNamespace, PolicyBindings: policyBindings, } authorizer := NewAuthorizer(testMasterNamespace, policyRegistry, policyBindingRegistry) actualAllowed, actualReason, actualError := authorizer.Authorize(*test.attributes) matchBool(test.expectedAllowed, actualAllowed, "allowed", t) if actualAllowed { containsString(test.expectedReason, actualReason, "allowReason", t) } else { containsString(test.expectedReason, actualReason, "denyReason", t) matchError(test.expectedError, actualError, "error", t) } } func matchString(expected, actual string, field string, t *testing.T) { if expected != actual { t.Errorf("%v: Expected %v, got %v", field, expected, actual) } } func containsString(expected, actual string, field string, t *testing.T) { if len(expected) == 0 && len(actual) != 0 { t.Errorf("%v: Expected %v, got %v", field, expected, actual) return } if !strings.Contains(actual, expected) { t.Errorf("%v: Expected %v, got %v", field, expected, actual) } } func matchBool(expected, actual bool, field string, t *testing.T) { if expected != actual { t.Errorf("%v: Expected %v, got %v", field, expected, actual) } } func matchError(expected string, actual error, field string, t *testing.T) { if actual == nil { if len(expected) != 0 { t.Errorf("%v: Expected %v, got %v", field, expected, actual) return } else { return } } if actual != nil && len(expected) == 0 { t.Errorf("%v: Expected %v, got %v", field, expected, actual) return } if strings.Contains(actual.Error(), expected) { t.Errorf("%v: Expected %v, got %v", field, expected, actual) } } func newDefaultGlobalPolicy() ([]authorizationapi.Policy, []authorizationapi.PolicyBinding) { return append(make([]authorizationapi.Policy, 0, 0), *GetBootstrapPolicy(testMasterNamespace)), append(make([]authorizationapi.PolicyBinding, 0, 0), authorizationapi.PolicyBinding{ ObjectMeta: kapi.ObjectMeta{ Name: testMasterNamespace, Namespace: testMasterNamespace, }, RoleBindings: map[string]authorizationapi.RoleBinding{ "cluster-admins": { ObjectMeta: kapi.ObjectMeta{ Name: "cluster-admins", Namespace: testMasterNamespace, }, RoleRef: kapi.ObjectReference{ Name: "cluster-admin", Namespace: testMasterNamespace, }, // until we get components authenticating, mssing users will be given all rights. Yay, security! UserNames: []string{"ClusterAdmin"}, }, }, }, ) } func newAdzePolicy() ([]authorizationapi.Policy, []authorizationapi.PolicyBinding) { return append(make([]authorizationapi.Policy, 0, 0), authorizationapi.Policy{ ObjectMeta: kapi.ObjectMeta{ Name: authorizationapi.PolicyName, Namespace: "adze", }, Roles: map[string]authorizationapi.Role{ "restrictedViewer": { ObjectMeta: kapi.ObjectMeta{ Name: "admin", Namespace: "adze", }, Rules: append(make([]authorizationapi.PolicyRule, 0), authorizationapi.PolicyRule{ Verbs: []string{"watch", "list", "get"}, Resources: []string{"buildConfigs"}, }), }, }, }), append(make([]authorizationapi.PolicyBinding, 0, 0), authorizationapi.PolicyBinding{ ObjectMeta: kapi.ObjectMeta{ Name: testMasterNamespace, Namespace: "adze", }, RoleBindings: map[string]authorizationapi.RoleBinding{ "projectAdmins": { ObjectMeta: kapi.ObjectMeta{ Name: "projectAdmins", Namespace: "adze", }, RoleRef: kapi.ObjectReference{ Name: "admin", Namespace: testMasterNamespace, }, UserNames: []string{"Anna", "TeasedAdmin"}, }, "viewers": { ObjectMeta: kapi.ObjectMeta{ Name: "viewers", Namespace: "adze", }, RoleRef: kapi.ObjectReference{ Name: "view", Namespace: testMasterNamespace, }, UserNames: []string{"Valerie"}, }, "editors": { ObjectMeta: kapi.ObjectMeta{ Name: "editors", Namespace: "adze", }, RoleRef: kapi.ObjectReference{ Name: "edit", Namespace: testMasterNamespace, }, UserNames: []string{"Ellen"}, }, }, }, authorizationapi.PolicyBinding{ ObjectMeta: kapi.ObjectMeta{ Name: "adze", Namespace: "adze", }, RoleBindings: map[string]authorizationapi.RoleBinding{ "restrictedViewers": { ObjectMeta: kapi.ObjectMeta{ Name: "restrictedViewers", Namespace: "adze", }, RoleRef: kapi.ObjectReference{ Name: "restrictedViewer", Namespace: "adze", }, UserNames: []string{"Rachel"}, }, }, }, ) }