package admission import ( "fmt" "testing" "k8s.io/kubernetes/pkg/admission" kapi "k8s.io/kubernetes/pkg/api" apierrors "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/auth/user" ktestclient "k8s.io/kubernetes/pkg/client/testclient" "k8s.io/kubernetes/pkg/runtime" authorizationapi "github.com/openshift/origin/pkg/authorization/api" buildapi "github.com/openshift/origin/pkg/build/api" "github.com/openshift/origin/pkg/client" "github.com/openshift/origin/pkg/client/testclient" ) func TestBuildAdmission(t *testing.T) { tests := []struct { name string kind string resource string object runtime.Object reviewResponse *authorizationapi.SubjectAccessReviewResponse expectedResource string expectAccept bool }{ { name: "allowed source build", object: testBuild(buildapi.SourceBuildStrategyType), kind: "Build", resource: buildsResource, reviewResponse: reviewResponse(true, ""), expectedResource: authorizationapi.SourceBuildResource, expectAccept: true, }, { name: "denied docker build", object: testBuild(buildapi.DockerBuildStrategyType), kind: "Build", resource: buildsResource, reviewResponse: reviewResponse(false, "cannot create build of type docker build"), expectAccept: false, expectedResource: authorizationapi.DockerBuildResource, }, { name: "allowed custom build", object: testBuild(buildapi.CustomBuildStrategyType), kind: "Build", resource: buildsResource, reviewResponse: reviewResponse(true, ""), expectedResource: authorizationapi.CustomBuildResource, expectAccept: true, }, { name: "allowed build config", object: testBuildConfig(buildapi.DockerBuildStrategyType), kind: "BuildConfig", resource: buildConfigsResource, reviewResponse: reviewResponse(true, ""), expectAccept: true, expectedResource: authorizationapi.DockerBuildResource, }, { name: "forbidden build config", object: testBuildConfig(buildapi.CustomBuildStrategyType), kind: "BuildConfig", resource: buildConfigsResource, reviewResponse: reviewResponse(false, ""), expectAccept: false, expectedResource: authorizationapi.CustomBuildResource, }, } for _, test := range tests { c := NewBuildByStrategy(fakeClient(test.expectedResource, test.reviewResponse)) attrs := admission.NewAttributesRecord(test.object, test.kind, "default", "name", test.resource, "" /*subresource*/, admission.Create, fakeUser()) err := c.Admit(attrs) if err != nil && test.expectAccept { t.Errorf("%s: unexpected error: %v", test.name, err) } if (err == nil || !apierrors.IsForbidden(err)) && !test.expectAccept { t.Errorf("%s: expecting reject error", test.name) } } } func fakeUser() user.Info { return &user.DefaultInfo{ Name: "testuser", } } func fakeClient(expectedResource string, reviewResponse *authorizationapi.SubjectAccessReviewResponse) client.Interface { emptyResponse := &authorizationapi.SubjectAccessReviewResponse{} return &testclient.Fake{ ReactFn: func(action ktestclient.FakeAction) (runtime.Object, error) { if action.Action == "create-subjectAccessReview" { review, ok := action.Value.(*authorizationapi.SubjectAccessReview) if !ok { return emptyResponse, fmt.Errorf("unexpected object received: %#v", review) } if review.Resource != expectedResource { return emptyResponse, fmt.Errorf("unexpected resource received: %s. expected: %s", review.Resource, expectedResource) } return reviewResponse, nil } return nil, nil }, } } func testBuild(strategy buildapi.BuildStrategyType) *buildapi.Build { return &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{ Name: "test-build", }, Spec: buildapi.BuildSpec{ Strategy: buildapi.BuildStrategy{ Type: strategy, }, }, } } func testBuildConfig(strategy buildapi.BuildStrategyType) *buildapi.BuildConfig { return &buildapi.BuildConfig{ ObjectMeta: kapi.ObjectMeta{ Name: "test-buildconfig", }, Spec: buildapi.BuildConfigSpec{ BuildSpec: buildapi.BuildSpec{ Strategy: buildapi.BuildStrategy{ Type: strategy, }, }, }, } } func reviewResponse(allowed bool, msg string) *authorizationapi.SubjectAccessReviewResponse { return &authorizationapi.SubjectAccessReviewResponse{ Allowed: allowed, Reason: msg, } }