func TestAuthorizationRestrictedAccessForProjectAdmins(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } haroldClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "hammer-project", "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } markClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "mallet-project", "mark") if err != nil { t.Fatalf("unexpected error: %v", err) } _, err = haroldClient.DeploymentConfigs("hammer-project").List(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } _, err = markClient.DeploymentConfigs("hammer-project").List(kapi.ListOptions{}) if (err == nil) || !kapierror.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } // projects are a special case where a get of a project actually sets a namespace. Make sure that // the namespace is properly special cased and set for authorization rules _, err = haroldClient.Projects().Get("hammer-project") if err != nil { t.Fatalf("unexpected error: %v", err) } _, err = markClient.Projects().Get("hammer-project") if (err == nil) || !kapierror.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } // wait for the project authorization cache to catch the change. It is on a one second period waitForProject(t, haroldClient, "hammer-project", 1*time.Second, 10) waitForProject(t, markClient, "mallet-project", 1*time.Second, 10) }
func createProject(osClient *osclient.Client, clientConfig *restclient.Config, name string) (*sdnapi.NetNamespace, error) { _, err := testserver.CreateNewProject(osClient, *clientConfig, name, name) if err != nil { return nil, fmt.Errorf("error creating project %q: %v", name, err) } backoff := utilwait.Backoff{ Duration: 100 * time.Millisecond, Factor: 2, Steps: 5, } var netns *sdnapi.NetNamespace err = utilwait.ExponentialBackoff(backoff, func() (bool, error) { netns, err = osClient.NetNamespaces().Get(name) if kapierrors.IsNotFound(err) { return false, nil } else if err != nil { return false, err } return true, nil }) if err != nil { return nil, fmt.Errorf("could not get NetNamepsace %q: %v", name, err) } return netns, nil }
func setupClusterResourceOverrideTest(t *testing.T, pluginConfig *overrideapi.ClusterResourceOverrideConfig) kclient.Interface { masterConfig, err := testserver.DefaultMasterOptions() checkErr(t, err) // fill in possibly-empty config values if masterConfig.KubernetesMasterConfig == nil { masterConfig.KubernetesMasterConfig = &api.KubernetesMasterConfig{} } kubeMaster := masterConfig.KubernetesMasterConfig if kubeMaster.AdmissionConfig.PluginConfig == nil { kubeMaster.AdmissionConfig.PluginConfig = map[string]api.AdmissionPluginConfig{} } // set our config as desired kubeMaster.AdmissionConfig.PluginConfig[overrideapi.PluginName] = api.AdmissionPluginConfig{Configuration: pluginConfig} // start up a server and return useful clients to that server clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterConfig) checkErr(t, err) clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) checkErr(t, err) clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) checkErr(t, err) // need to create a project and return client for project admin clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) checkErr(t, err) _, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, testutil.Namespace(), "peon") checkErr(t, err) checkErr(t, testserver.WaitForServiceAccounts(clusterAdminKubeClient, testutil.Namespace(), []string{bootstrappolicy.DefaultServiceAccountName})) return clusterAdminKubeClient }
func setupBuildStrategyTest(t *testing.T) (clusterAdminClient, projectAdminClient, projectEditorClient *client.Client) { namespace := testutil.Namespace() _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err = testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } projectAdminClient, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, namespace, "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } projectEditorClient, _, _, err = testutil.GetClientForUser(*clusterAdminClientConfig, "joe") if err != nil { t.Fatalf("unexpected error: %v", err) } addJoe := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.EditRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor(namespace, projectAdminClient), Users: []string{"joe"}, } if err := addJoe.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } if err := testutil.WaitForPolicyUpdate(projectEditorClient, namespace, "create", authorizationapi.DockerBuildResource, true); err != nil { t.Fatalf(err.Error()) } // Create builder image stream and tag imageStream := &imageapi.ImageStream{} imageStream.Name = "builderimage" _, err = clusterAdminClient.ImageStreams(testutil.Namespace()).Create(imageStream) if err != nil { t.Fatalf("Couldn't create ImageStream: %v", err) } // Create image stream mapping imageStreamMapping := &imageapi.ImageStreamMapping{} imageStreamMapping.Name = "builderimage" imageStreamMapping.Tag = "latest" imageStreamMapping.Image.Name = "image-id" imageStreamMapping.Image.DockerImageReference = "test/builderimage:latest" err = clusterAdminClient.ImageStreamMappings(testutil.Namespace()).Create(imageStreamMapping) if err != nil { t.Fatalf("Couldn't create ImageStreamMapping: %v", err) } return }
func TestDeployScale(t *testing.T) { const namespace = "test-deploy-scale" testutil.RequireEtcd(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() checkErr(t, err) clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) checkErr(t, err) clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) checkErr(t, err) _, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, namespace, "my-test-user") checkErr(t, err) osClient, _, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "my-test-user") checkErr(t, err) config := deploytest.OkDeploymentConfig(0) config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{} config.Spec.Replicas = 1 dc, err := osClient.DeploymentConfigs(namespace).Create(config) if err != nil { t.Fatalf("Couldn't create DeploymentConfig: %v %#v", err, config) } scale, err := osClient.DeploymentConfigs(namespace).GetScale(config.Name) if err != nil { t.Fatalf("Couldn't get DeploymentConfig scale: %v", err) } if scale.Spec.Replicas != 1 { t.Fatalf("Expected scale.spec.replicas=1, got %#v", scale) } scaleUpdate := &extensions.Scale{ ObjectMeta: kapi.ObjectMeta{ Name: dc.Name, Namespace: namespace, }, Spec: extensions.ScaleSpec{Replicas: 3}, } updatedScale, err := osClient.DeploymentConfigs(namespace).UpdateScale(scaleUpdate) if err != nil { // If this complains about "Scale" not being registered in "v1", check the kind overrides in the API registration in SubresourceGroupVersionKind t.Fatalf("Couldn't update DeploymentConfig scale to %#v: %v", scaleUpdate, err) } if updatedScale.Spec.Replicas != 3 { t.Fatalf("Expected scale.spec.replicas=3, got %#v", scale) } persistedScale, err := osClient.DeploymentConfigs(namespace).GetScale(config.Name) if err != nil { t.Fatalf("Couldn't get DeploymentConfig scale: %v", err) } if persistedScale.Spec.Replicas != 3 { t.Fatalf("Expected scale.spec.replicas=3, got %#v", scale) } }
func TestScopedImpersonation(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } projectName := "hammer-project" userName := "******" if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projectName, userName); err != nil { t.Fatalf("unexpected error: %v", err) } err = clusterAdminClient.Get(). SetHeader(authenticationapi.ImpersonateUserHeader, "harold"). SetHeader(authenticationapi.ImpersonateUserScopeHeader, "user:info"). Namespace(projectName).Resource("builds").Name("name").Do().Into(&buildapi.Build{}) if !kapierrors.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } user := &userapi.User{} err = clusterAdminClient.Get(). SetHeader(authenticationapi.ImpersonateUserHeader, "harold"). SetHeader(authenticationapi.ImpersonateUserScopeHeader, "user:info"). Resource("users").Name("~").Do().Into(user) if err != nil { t.Fatalf("unexpected error: %v", err) } if user.Name != "harold" { t.Fatalf("expected %v, got %v", "harold", user.Name) } }
func setup(t *testing.T) *client.Client { _, clusterAdminKubeConfigFile, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfigFile) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfigFile) if err != nil { t.Fatalf("unexpected error: %v", err) } projectAdminClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminKubeConfig, testutil.Namespace(), testutil.Namespace()) if err != nil { t.Fatalf("unexpected error: %v", err) } return projectAdminClient }
// TestOldLocalResourceAccessReviewEndpoint checks to make sure that the old resource access review endpoint still functions properly // this is needed to support old who-can client func TestOldLocalResourceAccessReviewEndpoint(t *testing.T) { _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } haroldClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "hammer-project", "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } namespace := "hammer-project" // simple check { rar := &authorizationapi.ResourceAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Verb: "get", Resource: "imagestreams/layers", }, } actualResponse := &authorizationapi.ResourceAccessReviewResponse{} err := haroldClient.Post().Namespace(namespace).Resource("resourceAccessReviews").Body(rar).Do().Into(actualResponse) if err != nil { t.Errorf("unexpected error: %v", err) } expectedResponse := &authorizationapi.ResourceAccessReviewResponse{ Namespace: namespace, Users: sets.NewString("harold", "system:serviceaccount:hammer-project:builder"), Groups: sets.NewString("system:cluster-admins", "system:masters", "system:serviceaccounts:hammer-project"), } if (actualResponse.Namespace != expectedResponse.Namespace) || !reflect.DeepEqual(actualResponse.Users.List(), expectedResponse.Users.List()) || !reflect.DeepEqual(actualResponse.Groups.List(), expectedResponse.Groups.List()) { t.Errorf("review\n\t%#v\nexpected\n\t%#v\ngot\n\t%#v", rar, expectedResponse, actualResponse) } } // namespace forced to allowed namespace so we can't trick the server into leaking { rar := &authorizationapi.ResourceAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Namespace: "sneaky-user", Verb: "get", Resource: "imagestreams/layers", }, } actualResponse := &authorizationapi.ResourceAccessReviewResponse{} err := haroldClient.Post().Namespace(namespace).Resource("resourceAccessReviews").Body(rar).Do().Into(actualResponse) if err != nil { t.Errorf("unexpected error: %v", err) } expectedResponse := &authorizationapi.ResourceAccessReviewResponse{ Namespace: namespace, Users: sets.NewString("harold", "system:serviceaccount:hammer-project:builder"), Groups: sets.NewString("system:cluster-admins", "system:masters", "system:serviceaccounts:hammer-project"), } if (actualResponse.Namespace != expectedResponse.Namespace) || !reflect.DeepEqual(actualResponse.Users.List(), expectedResponse.Users.List()) || !reflect.DeepEqual(actualResponse.Groups.List(), expectedResponse.Groups.List()) { t.Errorf("review\n\t%#v\nexpected\n\t%#v\ngot\n\t%#v", rar, expectedResponse, actualResponse) } } }
func TestAuthorizationSubjectAccessReview(t *testing.T) { _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } haroldClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "hammer-project", "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } markClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "mallet-project", "mark") if err != nil { t.Fatalf("unexpected error: %v", err) } dannyClient, _, dannyConfig, err := testutil.GetClientForUser(*clusterAdminClientConfig, "danny") if err != nil { t.Fatalf("error requesting token: %v", err) } addDanny := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.ViewRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor("default", clusterAdminClient), Users: []string{"danny"}, } if err := addDanny.AddRole(); err != nil { t.Errorf("unexpected error: %v", err) } askCanDannyGetProject := &authorizationapi.SubjectAccessReview{ User: "******", Action: authorizationapi.AuthorizationAttributes{Verb: "get", Resource: "projects"}, } subjectAccessReviewTest{ description: "cluster admin told danny can get project default", localInterface: clusterAdminClient.LocalSubjectAccessReviews("default"), localReview: &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.AuthorizationAttributes{Verb: "get", Resource: "projects"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by rule in default", Namespace: "default", }, }.run(t) subjectAccessReviewTest{ description: "cluster admin told danny cannot get projects cluster-wide", clusterInterface: clusterAdminClient.SubjectAccessReviews(), clusterReview: askCanDannyGetProject, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "danny" cannot get projects at the cluster scope`, Namespace: "", }, }.run(t) subjectAccessReviewTest{ description: "as danny, can I make cluster subject access reviews", clusterInterface: dannyClient.SubjectAccessReviews(), clusterReview: askCanDannyGetProject, err: `User "danny" cannot create subjectaccessreviews at the cluster scope`, }.run(t) addValerie := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.ViewRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor("hammer-project", haroldClient), Users: []string{"valerie"}, } if err := addValerie.AddRole(); err != nil { t.Errorf("unexpected error: %v", err) } addEdgar := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.EditRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor("mallet-project", markClient), Users: []string{"edgar"}, } if err := addEdgar.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } askCanValerieGetProject := &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.AuthorizationAttributes{Verb: "get", Resource: "projects"}, } subjectAccessReviewTest{ description: "harold told valerie can get project hammer-project", localInterface: haroldClient.LocalSubjectAccessReviews("hammer-project"), localReview: askCanValerieGetProject, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by rule in hammer-project", Namespace: "hammer-project", }, }.run(t) subjectAccessReviewTest{ description: "mark told valerie cannot get project mallet-project", localInterface: markClient.LocalSubjectAccessReviews("mallet-project"), localReview: askCanValerieGetProject, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "valerie" cannot get projects in project "mallet-project"`, Namespace: "mallet-project", }, }.run(t) askCanEdgarDeletePods := &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.AuthorizationAttributes{Verb: "delete", Resource: "pods"}, } subjectAccessReviewTest{ description: "mark told edgar can delete pods in mallet-project", localInterface: markClient.LocalSubjectAccessReviews("mallet-project"), localReview: askCanEdgarDeletePods, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by rule in mallet-project", Namespace: "mallet-project", }, }.run(t) subjectAccessReviewTest{ description: "harold denied ability to run subject access review in project mallet-project", localInterface: haroldClient.LocalSubjectAccessReviews("mallet-project"), localReview: askCanEdgarDeletePods, err: `User "harold" cannot create localsubjectaccessreviews in project "mallet-project"`, }.run(t) askCanHaroldUpdateProject := &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.AuthorizationAttributes{Verb: "update", Resource: "projects"}, } subjectAccessReviewTest{ description: "harold told harold can update project hammer-project", localInterface: haroldClient.LocalSubjectAccessReviews("hammer-project"), localReview: askCanHaroldUpdateProject, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by rule in hammer-project", Namespace: "hammer-project", }, }.run(t) askCanClusterAdminsCreateProject := &authorizationapi.SubjectAccessReview{ Groups: sets.NewString("system:cluster-admins"), Action: authorizationapi.AuthorizationAttributes{Verb: "create", Resource: "projects"}, } subjectAccessReviewTest{ description: "cluster admin told cluster admins can create projects", clusterInterface: clusterAdminClient.SubjectAccessReviews(), clusterReview: askCanClusterAdminsCreateProject, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by cluster rule", Namespace: "", }, }.run(t) subjectAccessReviewTest{ description: "harold denied ability to run cluster subject access review", clusterInterface: haroldClient.SubjectAccessReviews(), clusterReview: askCanClusterAdminsCreateProject, err: `User "harold" cannot create subjectaccessreviews at the cluster scope`, }.run(t) askCanICreatePods := &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "create", Resource: "pods"}, } subjectAccessReviewTest{ description: "harold told he can create pods in project hammer-project", localInterface: haroldClient.LocalSubjectAccessReviews("hammer-project"), localReview: askCanICreatePods, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by rule in hammer-project", Namespace: "hammer-project", }, }.run(t) askCanICreatePolicyBindings := &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "create", Resource: "policybindings"}, } subjectAccessReviewTest{ description: "harold told he can create policybindings in project hammer-project", localInterface: haroldClient.LocalSubjectAccessReviews("hammer-project"), localReview: askCanICreatePolicyBindings, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "harold" cannot create policybindings in project "hammer-project"`, Namespace: "hammer-project", }, }.run(t) // impersonate SAR tests // impersonated empty token SAR shouldn't be allowed at all // impersonated danny token SAR shouldn't be allowed to see pods in hammer or in cluster // impersonated danny token SAR should be allowed to see pods in default // we need a token client for overriding if err != nil { t.Fatalf("unexpected error: %v", err) } otherAdminClient, _, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "other-admin") if err != nil { t.Fatalf("error requesting token: %v", err) } addOtherAdmin := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.ClusterAdminRoleName, RoleBindingAccessor: policy.NewClusterRoleBindingAccessor(clusterAdminClient), Users: []string{"other-admin"}, } if err := addOtherAdmin.AddRole(); err != nil { t.Errorf("unexpected error: %v", err) } subjectAccessReviewTest{ description: "empty token impersonate can't see pods in namespace", localInterface: otherAdminClient.ImpersonateLocalSubjectAccessReviews("hammer-project", ""), localReview: &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "list", Resource: "pods"}, }, err: `impersonating token may not be empty`, }.run(t) subjectAccessReviewTest{ description: "empty token impersonate can't see pods in cluster", clusterInterface: otherAdminClient.ImpersonateSubjectAccessReviews(""), clusterReview: &authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "list", Resource: "pods"}, }, err: `impersonating token may not be empty`, }.run(t) subjectAccessReviewTest{ description: "danny impersonate can't see pods in hammer namespace", localInterface: otherAdminClient.ImpersonateLocalSubjectAccessReviews("hammer-project", dannyConfig.BearerToken), localReview: &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "list", Resource: "pods"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "danny" cannot list pods in project "hammer-project"`, Namespace: "hammer-project", }, }.run(t) subjectAccessReviewTest{ description: "danny impersonate can't see pods in cluster", clusterInterface: otherAdminClient.ImpersonateSubjectAccessReviews(dannyConfig.BearerToken), clusterReview: &authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "list", Resource: "pods"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "danny" cannot list all pods in the cluster`, }, }.run(t) subjectAccessReviewTest{ description: "danny impersonate can see pods in default", localInterface: otherAdminClient.ImpersonateLocalSubjectAccessReviews("default", dannyConfig.BearerToken), localReview: &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "list", Resource: "pods"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: `allowed by rule in default`, Namespace: "default", }, }.run(t) }
func TestEndpointAdmission(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("error creating config: %v", err) } masterConfig.KubernetesMasterConfig.AdmissionConfig.PluginConfig = map[string]configapi.AdmissionPluginConfig{ "RestrictedEndpointsAdmission": { Configuration: &configapi.DefaultAdmissionConfig{}, }, } masterConfig.NetworkConfig.ClusterNetworkCIDR = clusterNetworkCIDR masterConfig.NetworkConfig.ServiceNetworkCIDR = serviceNetworkCIDR kubeConfigFile, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("error starting server: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(kubeConfigFile) if err != nil { t.Fatalf("error getting kube client: %v", err) } clusterAdminOSClient, err := testutil.GetClusterAdminClient(kubeConfigFile) if err != nil { t.Fatalf("error getting client: %v", err) } clientConfig, err := testutil.GetClusterAdminClientConfig(kubeConfigFile) if err != nil { t.Fatalf("error getting client config: %v", err) } // Cluster admin testOne(t, clusterAdminKubeClient, "default", "cluster", true) testOne(t, clusterAdminKubeClient, "default", "service", true) testOne(t, clusterAdminKubeClient, "default", "external", true) // Endpoint controller service account _, serviceAccountClient, _, err := testutil.GetClientForServiceAccount(clusterAdminKubeClient, *clientConfig, bootstrappolicy.DefaultOpenShiftInfraNamespace, bootstrappolicy.InfraEndpointControllerServiceAccountName) if err != nil { t.Fatalf("error getting endpoint controller service account: %v", err) } testOne(t, serviceAccountClient, "default", "cluster", true) testOne(t, serviceAccountClient, "default", "service", true) testOne(t, serviceAccountClient, "default", "external", true) // Project admin _, err = testserver.CreateNewProject(clusterAdminOSClient, *clientConfig, "myproject", "myadmin") if err != nil { t.Fatalf("error creating project: %v", err) } _, projectAdminClient, _, err := testutil.GetClientForUser(*clientConfig, "myadmin") if err != nil { t.Fatalf("error getting project admin client: %v", err) } testOne(t, projectAdminClient, "myproject", "cluster", false) testOne(t, projectAdminClient, "myproject", "service", false) testOne(t, projectAdminClient, "myproject", "external", true) // User without restricted endpoint permission can't modify IPs but can still do other modifications ep := testOne(t, clusterAdminKubeClient, "myproject", "cluster", true) ep.Annotations = map[string]string{"foo": "bar"} ep, err = projectAdminClient.Endpoints("myproject").Update(ep) if err != nil { t.Fatalf("unexpected error updating endpoint annotation: %v", err) } ep.Subsets[0].Addresses[0].IP = exampleAddresses["service"] ep, err = projectAdminClient.Endpoints("myproject").Update(ep) if err == nil { t.Fatalf("unexpected success modifying endpoint") } }
func TestTriggers_imageChange(t *testing.T) { _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("error starting master: %v", err) } openshiftClusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("error getting cluster admin client: %v", err) } openshiftClusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("error getting cluster admin client config: %v", err) } openshiftProjectAdminClient, err := testserver.CreateNewProject(openshiftClusterAdminClient, *openshiftClusterAdminClientConfig, testutil.Namespace(), "bob") if err != nil { t.Fatalf("error creating project: %v", err) } imageStream := &imageapi.ImageStream{ObjectMeta: kapi.ObjectMeta{Name: "test-image-stream"}} config := deploytest.OkDeploymentConfig(0) config.Namespace = testutil.Namespace() configWatch, err := openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Watch(labels.Everything(), fields.Everything(), "0") if err != nil { t.Fatalf("Couldn't subscribe to Deployments %v", err) } defer configWatch.Stop() if imageStream, err = openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Create(imageStream); err != nil { t.Fatalf("Couldn't create ImageStream: %v", err) } imageWatch, err := openshiftProjectAdminClient.ImageStreams(testutil.Namespace()).Watch(labels.Everything(), fields.Everything(), "0") if err != nil { t.Fatalf("Couldn't subscribe to ImageStreams: %s", err) } defer imageWatch.Stop() updatedImage := "sha256:00000000000000000000000000000001" updatedPullSpec := fmt.Sprintf("registry:8080/openshift/test-image@%s", updatedImage) // Make a function which can create a new tag event for the image stream and // then wait for the stream status to be asynchronously updated. createTagEvent := func() { mapping := &imageapi.ImageStreamMapping{ ObjectMeta: kapi.ObjectMeta{Name: imageStream.Name}, Tag: "latest", Image: imageapi.Image{ ObjectMeta: kapi.ObjectMeta{ Name: updatedImage, }, DockerImageReference: updatedPullSpec, }, } if err := openshiftProjectAdminClient.ImageStreamMappings(testutil.Namespace()).Create(mapping); err != nil { t.Fatalf("unexpected error: %v", err) } t.Log("Waiting for image stream mapping to be reflected in the IS status...") statusLoop: for { select { case event := <-imageWatch.ResultChan(): stream := event.Object.(*imageapi.ImageStream) if _, ok := stream.Status.Tags["latest"]; ok { t.Logf("ImageStream %s now has Status with tags: %#v", stream.Name, stream.Status.Tags) break statusLoop } else { t.Logf("Still waiting for latest tag status on ImageStream %s", stream.Name) } } } } if config, err = openshiftProjectAdminClient.DeploymentConfigs(testutil.Namespace()).Create(config); err != nil { t.Fatalf("Couldn't create DeploymentConfig: %v", err) } createTagEvent() var newConfig *deployapi.DeploymentConfig t.Log("Waiting for a new deployment config in response to ImageStream update") waitForNewConfig: for { select { case event := <-configWatch.ResultChan(): if event.Type == watchapi.Modified { newConfig = event.Object.(*deployapi.DeploymentConfig) // Multiple updates to the config can be expected (e.g. status // updates), so wait for a significant update (e.g. version). if newConfig.Status.LatestVersion > 0 { if e, a := updatedPullSpec, newConfig.Spec.Template.Spec.Containers[0].Image; e != a { t.Fatalf("unexpected image for pod template container 0; expected %q, got %q", e, a) } break waitForNewConfig } t.Log("Still waiting for a new deployment config in response to ImageStream update") } } } }
func TestTriggers_configChange(t *testing.T) { const namespace = "test-triggers-configchange" _, clusterAdminKubeConfig, err := testserver.StartTestMaster() checkErr(t, err) clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) checkErr(t, err) clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) checkErr(t, err) _, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, namespace, "my-test-user") checkErr(t, err) osClient, kubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "my-test-user") checkErr(t, err) config := deploytest.OkDeploymentConfig(0) config.Namespace = namespace config.Spec.Triggers[0] = deploytest.OkConfigChangeTrigger() rcWatch, err := kubeClient.ReplicationControllers(namespace).Watch(labels.Everything(), fields.Everything(), "0") if err != nil { t.Fatalf("Couldn't subscribe to Deployments %v", err) } defer rcWatch.Stop() // submit the initial deployment config if _, err := osClient.DeploymentConfigs(namespace).Create(config); err != nil { t.Fatalf("Couldn't create DeploymentConfig: %v", err) } // verify the initial deployment exists event := <-rcWatch.ResultChan() if e, a := watchapi.Added, event.Type; e != a { t.Fatalf("expected watch event type %s, got %s", e, a) } deployment := event.Object.(*kapi.ReplicationController) if e, a := config.Name, deployutil.DeploymentConfigNameFor(deployment); e != a { t.Fatalf("Expected deployment annotated with deploymentConfig '%s', got '%s'", e, a) } assertEnvVarEquals("ENV1", "VAL1", deployment, t) retryErr := kclient.RetryOnConflict(wait.Backoff{Steps: maxUpdateRetries}, func() error { // submit a new config with an updated environment variable config, err := osClient.DeploymentConfigs(namespace).Generate(config.Name) if err != nil { return err } config.Spec.Template.Spec.Containers[0].Env[0].Value = "UPDATED" // before we update the config, we need to update the state of the existing deployment // this is required to be done manually since the deployment and deployer pod controllers are not run in this test // get this live or conflicts will never end up resolved liveDeployment, err := kubeClient.ReplicationControllers(deployment.Namespace).Get(deployment.Name) if err != nil { return err } liveDeployment.Annotations[deployapi.DeploymentStatusAnnotation] = string(deployapi.DeploymentStatusComplete) // update the deployment if _, err := kubeClient.ReplicationControllers(namespace).Update(liveDeployment); err != nil { return err } event = <-rcWatch.ResultChan() if e, a := watchapi.Modified, event.Type; e != a { t.Fatalf("expected watch event type %s, got %s", e, a) } if _, err := osClient.DeploymentConfigs(namespace).Update(config); err != nil { return err } return nil }) if retryErr != nil { t.Fatal(retryErr) } var newDeployment *kapi.ReplicationController for { event = <-rcWatch.ResultChan() if event.Type != watchapi.Added { // Discard modifications which could be applied to the original RC, etc. continue } newDeployment = event.Object.(*kapi.ReplicationController) break } assertEnvVarEquals("ENV1", "UPDATED", newDeployment, t) if newDeployment.Name == deployment.Name { t.Fatalf("expected new deployment; old=%s, new=%s", deployment.Name, newDeployment.Name) } }
func TestExtensionsAPIDeletion(t *testing.T) { const projName = "ext-deletion-proj" testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // create the containing project if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projName, "admin"); err != nil { t.Fatalf("unexpected error creating the project: %v", err) } projectAdminClient, projectAdminKubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "admin") if err != nil { t.Fatalf("unexpected error getting project admin client: %v", err) } if err := testutil.WaitForPolicyUpdate(projectAdminClient, projName, "get", expapi.Resource("horizontalpodautoscalers"), true); err != nil { t.Fatalf("unexpected error waiting for policy update: %v", err) } // create the extensions resources as the project admin percent := int32(10) hpa := autoscaling.HorizontalPodAutoscaler{ ObjectMeta: kapi.ObjectMeta{Name: "test-hpa"}, Spec: autoscaling.HorizontalPodAutoscalerSpec{ ScaleTargetRef: autoscaling.CrossVersionObjectReference{Kind: "DeploymentConfig", Name: "frontend", APIVersion: "v1"}, MaxReplicas: 10, TargetCPUUtilizationPercentage: &percent, }, } if _, err := projectAdminKubeClient.Autoscaling().HorizontalPodAutoscalers(projName).Create(&hpa); err != nil { t.Fatalf("unexpected error creating the HPA object: %v", err) } job := batch.Job{ ObjectMeta: kapi.ObjectMeta{Name: "test-job"}, Spec: batch.JobSpec{ Template: kapi.PodTemplateSpec{ ObjectMeta: kapi.ObjectMeta{Labels: map[string]string{"foo": "bar"}}, Spec: kapi.PodSpec{ Containers: []kapi.Container{{Name: "baz", Image: "run"}}, RestartPolicy: kapi.RestartPolicyOnFailure, }, }, }, } if _, err := projectAdminKubeClient.Extensions().Jobs(projName).Create(&job); err != nil { t.Fatalf("unexpected error creating the job object: %v", err) } if err := clusterAdminClient.Projects().Delete(projName); err != nil { t.Fatalf("unexpected error deleting the project: %v", err) } err = wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) { _, err := clusterAdminKubeClient.Namespaces().Get(projName) if errors.IsNotFound(err) { return true, nil } return false, err }) if err != nil { t.Fatalf("unexpected error while waiting for project to delete: %v", err) } if _, err := clusterAdminKubeClient.Autoscaling().HorizontalPodAutoscalers(projName).Get(hpa.Name); err == nil { t.Fatalf("HPA object was still present after project was deleted!") } else if !errors.IsNotFound(err) { t.Fatalf("Error trying to get deleted HPA object (not a not-found error): %v", err) } if _, err := clusterAdminKubeClient.Extensions().Jobs(projName).Get(job.Name); err == nil { t.Fatalf("Job object was still present after project was deleted!") } else if !errors.IsNotFound(err) { t.Fatalf("Error trying to get deleted Job object (not a not-found error): %v", err) } }
func TestSAAsOAuthClient(t *testing.T) { testutil.RequireEtcd(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } authorizationCodes := make(chan string, 1) authorizationErrors := make(chan string, 1) oauthServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { t.Logf("fake pod server got %v", req.URL) if code := req.URL.Query().Get("code"); len(code) > 0 { authorizationCodes <- code } if err := req.URL.Query().Get("error"); len(err) > 0 { authorizationErrors <- err } })) defer oauthServer.Close() clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } projectName := "hammer-project" if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projectName, "harold"); err != nil { t.Fatalf("unexpected error: %v", err) } if err := testserver.WaitForServiceAccounts(clusterAdminKubeClient, projectName, []string{"default"}); err != nil { t.Fatalf("unexpected error: %v", err) } // get the SA ready with redirect URIs and secret annotations var defaultSA *kapi.ServiceAccount // retry this a couple times. We seem to be flaking on update conflicts and missing secrets all together err = kclient.RetryOnConflict(kclient.DefaultRetry, func() error { defaultSA, err = clusterAdminKubeClient.ServiceAccounts(projectName).Get("default") if err != nil { return err } if defaultSA.Annotations == nil { defaultSA.Annotations = map[string]string{} } defaultSA.Annotations[saoauth.OAuthRedirectURISecretAnnotationPrefix+"one"] = oauthServer.URL defaultSA.Annotations[saoauth.OAuthWantChallengesAnnotationPrefix] = "true" defaultSA, err = clusterAdminKubeClient.ServiceAccounts(projectName).Update(defaultSA) return err }) if err != nil { t.Fatalf("unexpected error: %v", err) } var oauthSecret *kapi.Secret // retry this a couple times. We seem to be flaking on update conflicts and missing secrets all together err = wait.PollImmediate(30*time.Millisecond, 10*time.Second, func() (done bool, err error) { allSecrets, err := clusterAdminKubeClient.Secrets(projectName).List(kapi.ListOptions{}) if err != nil { return false, err } for i := range allSecrets.Items { secret := allSecrets.Items[i] if serviceaccount.IsServiceAccountToken(&secret, defaultSA) { oauthSecret = &secret return true, nil } } return false, nil }) if err != nil { t.Fatalf("unexpected error: %v", err) } oauthClientConfig := &osincli.ClientConfig{ ClientId: serviceaccount.MakeUsername(defaultSA.Namespace, defaultSA.Name), ClientSecret: string(oauthSecret.Data[kapi.ServiceAccountTokenKey]), AuthorizeUrl: clusterAdminClientConfig.Host + "/oauth/authorize", TokenUrl: clusterAdminClientConfig.Host + "/oauth/token", RedirectUrl: oauthServer.URL, Scope: scope.Join([]string{"user:info", "role:edit:" + projectName}), SendClientSecretInParams: true, } runOAuthFlow(t, clusterAdminClientConfig, projectName, oauthClientConfig, authorizationCodes, authorizationErrors, true, true) clusterAdminClient.OAuthClientAuthorizations().Delete("harold:" + oauthClientConfig.ClientId) oauthClientConfig = &osincli.ClientConfig{ ClientId: serviceaccount.MakeUsername(defaultSA.Namespace, defaultSA.Name), ClientSecret: string(oauthSecret.Data[kapi.ServiceAccountTokenKey]), AuthorizeUrl: clusterAdminClientConfig.Host + "/oauth/authorize", TokenUrl: clusterAdminClientConfig.Host + "/oauth/token", RedirectUrl: oauthServer.URL, Scope: scope.Join([]string{"user:info", "role:edit:other-ns"}), SendClientSecretInParams: true, } runOAuthFlow(t, clusterAdminClientConfig, projectName, oauthClientConfig, authorizationCodes, authorizationErrors, false, false) clusterAdminClient.OAuthClientAuthorizations().Delete("harold:" + oauthClientConfig.ClientId) oauthClientConfig = &osincli.ClientConfig{ ClientId: serviceaccount.MakeUsername(defaultSA.Namespace, defaultSA.Name), ClientSecret: string(oauthSecret.Data[kapi.ServiceAccountTokenKey]), AuthorizeUrl: clusterAdminClientConfig.Host + "/oauth/authorize", TokenUrl: clusterAdminClientConfig.Host + "/oauth/token", RedirectUrl: oauthServer.URL, Scope: scope.Join([]string{"user:info"}), SendClientSecretInParams: true, } runOAuthFlow(t, clusterAdminClientConfig, projectName, oauthClientConfig, authorizationCodes, authorizationErrors, true, false) clusterAdminClient.OAuthClientAuthorizations().Delete("harold:" + oauthClientConfig.ClientId) }
func TestExtensionsAPIDisabledAutoscaleBatchEnabled(t *testing.T) { const projName = "ext-disabled-batch-enabled-proj" testutil.RequireEtcd(t) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("unexpected error: %v", err) } // Disable all extensions API versions // Leave autoscaling/batch APIs enabled masterConfig.KubernetesMasterConfig.DisabledAPIGroupVersions = map[string][]string{"extensions": {"*"}} clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // create the containing project if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projName, "admin"); err != nil { t.Fatalf("unexpected error creating the project: %v", err) } projectAdminClient, projectAdminKubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "admin") if err != nil { t.Fatalf("unexpected error getting project admin client: %v", err) } if err := testutil.WaitForPolicyUpdate(projectAdminClient, projName, "get", expapi.Resource("horizontalpodautoscalers"), true); err != nil { t.Fatalf("unexpected error waiting for policy update: %v", err) } validHPA := &expapi.HorizontalPodAutoscaler{ ObjectMeta: kapi.ObjectMeta{Name: "myjob"}, Spec: expapi.HorizontalPodAutoscalerSpec{ ScaleRef: expapi.SubresourceReference{Name: "foo", Kind: "ReplicationController", Subresource: "scale"}, MaxReplicas: 1, }, } validJob := &batch.Job{ ObjectMeta: kapi.ObjectMeta{Name: "myjob"}, Spec: batch.JobSpec{ Template: kapi.PodTemplateSpec{ Spec: kapi.PodSpec{ Containers: []kapi.Container{{Name: "mycontainer", Image: "myimage"}}, RestartPolicy: kapi.RestartPolicyNever, }, }, }, } // make sure extensions API objects cannot be listed or created if _, err := projectAdminKubeClient.Extensions().HorizontalPodAutoscalers(projName).List(kapi.ListOptions{}); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error listing HPA, got %v", err) } if _, err := projectAdminKubeClient.Extensions().HorizontalPodAutoscalers(projName).Create(validHPA); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error creating HPA, got %v", err) } if _, err := projectAdminKubeClient.Extensions().Jobs(projName).List(kapi.ListOptions{}); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error listing jobs, got %v", err) } if _, err := projectAdminKubeClient.Extensions().Jobs(projName).Create(validJob); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error creating job, got %v", err) } // make sure autoscaling and batch API objects can be listed and created if _, err := projectAdminKubeClient.Autoscaling().HorizontalPodAutoscalers(projName).List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %#v", err) } if _, err := projectAdminKubeClient.Autoscaling().HorizontalPodAutoscalers(projName).Create(validHPA); err != nil { t.Fatalf("unexpected error: %#v", err) } if _, err := projectAdminKubeClient.Batch().Jobs(projName).List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %#v", err) } if _, err := projectAdminKubeClient.Batch().Jobs(projName).Create(validJob); err != nil { t.Fatalf("unexpected error: %#v", err) } // Delete the containing project if err := testutil.DeleteAndWaitForNamespaceTermination(clusterAdminKubeClient, projName); err != nil { t.Fatalf("unexpected error: %#v", err) } // recreate the containing project if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projName, "admin"); err != nil { t.Fatalf("unexpected error creating the project: %v", err) } projectAdminClient, projectAdminKubeClient, _, err = testutil.GetClientForUser(*clusterAdminClientConfig, "admin") if err != nil { t.Fatalf("unexpected error getting project admin client: %v", err) } if err := testutil.WaitForPolicyUpdate(projectAdminClient, projName, "get", expapi.Resource("horizontalpodautoscalers"), true); err != nil { t.Fatalf("unexpected error waiting for policy update: %v", err) } // make sure the created objects got cleaned up by namespace deletion if hpas, err := projectAdminKubeClient.Autoscaling().HorizontalPodAutoscalers(projName).List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %#v", err) } else if len(hpas.Items) > 0 { t.Fatalf("expected 0 HPA objects, got %#v", hpas.Items) } if jobs, err := projectAdminKubeClient.Batch().Jobs(projName).List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %#v", err) } else if len(jobs.Items) > 0 { t.Fatalf("expected 0 Job objects, got %#v", jobs.Items) } }
func TestExtensionsAPIDisabled(t *testing.T) { const projName = "ext-disabled-proj" testutil.RequireEtcd(t) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("unexpected error: %v", err) } // Disable all extensions API versions masterConfig.KubernetesMasterConfig.DisabledAPIGroupVersions = map[string][]string{"extensions": {"*"}, "autoscaling": {"*"}, "batch": {"*"}} clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // create the containing project if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projName, "admin"); err != nil { t.Fatalf("unexpected error creating the project: %v", err) } projectAdminClient, projectAdminKubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "admin") if err != nil { t.Fatalf("unexpected error getting project admin client: %v", err) } if err := testutil.WaitForPolicyUpdate(projectAdminClient, projName, "get", expapi.Resource("horizontalpodautoscalers"), true); err != nil { t.Fatalf("unexpected error waiting for policy update: %v", err) } // make sure extensions API objects cannot be listed or created if _, err := projectAdminKubeClient.Extensions().HorizontalPodAutoscalers(projName).List(kapi.ListOptions{}); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error listing HPA, got %v", err) } if _, err := projectAdminKubeClient.Extensions().HorizontalPodAutoscalers(projName).Create(&expapi.HorizontalPodAutoscaler{}); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error creating HPA, got %v", err) } if _, err := projectAdminKubeClient.Extensions().Jobs(projName).List(kapi.ListOptions{}); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error listing jobs, got %v", err) } if _, err := projectAdminKubeClient.Extensions().Jobs(projName).Create(&batch.Job{}); !errors.IsNotFound(err) { t.Fatalf("expected NotFound error creating job, got %v", err) } // Delete the containing project if err := testutil.DeleteAndWaitForNamespaceTermination(clusterAdminKubeClient, projName); err != nil { t.Fatalf("unexpected error: %#v", err) } }
func TestExtensionsAPIDeletion(t *testing.T) { const projName = "ext-deletion-proj" _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // create the containing project if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projName, "admin"); err != nil { t.Fatalf("unexpected error creating the project: %v", err) } projectAdminClient, projectAdminKubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "admin") if err != nil { t.Fatalf("unexpected error getting project admin client: %v", err) } // TODO: switch to checking "list","horizontalpodautoscalers" once SAR supports API groups if err := testutil.WaitForPolicyUpdate(projectAdminClient, projName, "get", "pods", true); err != nil { t.Fatalf("unexpected error waiting for policy update: %v", err) } // create the extensions resources as the project admin hpa := expapi.HorizontalPodAutoscaler{ ObjectMeta: kapi.ObjectMeta{Name: "test-hpa"}, Spec: expapi.HorizontalPodAutoscalerSpec{ ScaleRef: expapi.SubresourceReference{Kind: "DeploymentConfig", Name: "frontend", APIVersion: "v1", Subresource: "scale"}, MaxReplicas: 10, CPUUtilization: &expapi.CPUTargetUtilization{TargetPercentage: 10}, }, } if _, err := projectAdminKubeClient.Extensions().HorizontalPodAutoscalers(projName).Create(&hpa); err != nil { t.Fatalf("unexpected error creating the HPA object: %v", err) } job := expapi.Job{ ObjectMeta: kapi.ObjectMeta{Name: "test-job"}, Spec: expapi.JobSpec{ Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, Template: kapi.PodTemplateSpec{ ObjectMeta: kapi.ObjectMeta{Labels: map[string]string{"foo": "bar"}}, Spec: kapi.PodSpec{ Containers: []kapi.Container{{Name: "baz", Image: "run"}}, RestartPolicy: kapi.RestartPolicyOnFailure, }, }, }, } if _, err := projectAdminKubeClient.Extensions().Jobs(projName).Create(&job); err != nil { t.Fatalf("unexpected error creating the job object: %v", err) } if err := clusterAdminClient.Projects().Delete(projName); err != nil { t.Fatalf("unexpected error deleting the project: %v", err) } err = wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) { _, err := clusterAdminKubeClient.Namespaces().Get(projName) if errors.IsNotFound(err) { return true, nil } return false, err }) if err != nil { t.Fatalf("unexpected error while waiting for project to delete: %v", err) } if _, err := clusterAdminKubeClient.Extensions().HorizontalPodAutoscalers(projName).Get(hpa.Name); err == nil { t.Fatalf("HPA object was still present after project was deleted!") } else if !errors.IsNotFound(err) { t.Fatalf("Error trying to get deleted HPA object (not a not-found error): %v", err) } if _, err := clusterAdminKubeClient.Extensions().Jobs(projName).Get(job.Name); err == nil { t.Fatalf("Job object was still present after project was deleted!") } else if !errors.IsNotFound(err) { t.Fatalf("Error trying to get deleted Job object (not a not-found error): %v", err) } }
func TestProjectWatch(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } bobClient, _, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "bob") if err != nil { t.Fatalf("unexpected error: %v", err) } w, err := bobClient.Projects().Watch(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "ns-01", "bob"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForAdd("ns-01", w, t) // TEST FOR ADD/REMOVE ACCESS joeClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "ns-02", "joe") if err != nil { t.Fatalf("unexpected error: %v", err) } addBob := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.EditRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor("ns-02", joeClient), Users: []string{"bob"}, } if err := addBob.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } waitForAdd("ns-02", w, t) if err := addBob.RemoveRole(); err != nil { t.Fatalf("unexpected error: %v", err) } waitForDelete("ns-02", w, t) // TEST FOR DELETE PROJECT if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "ns-03", "bob"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForAdd("ns-03", w, t) if err := bobClient.Projects().Delete("ns-03"); err != nil { t.Fatalf("unexpected error: %v", err) } // wait for the delete waitForDelete("ns-03", w, t) // test the "start from beginning watch" beginningWatch, err := bobClient.Projects().Watch(kapi.ListOptions{ResourceVersion: "0"}) if err != nil { t.Fatalf("unexpected error: %v", err) } waitForAdd("ns-01", beginningWatch, t) fromNowWatch, err := bobClient.Projects().Watch(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } select { case event := <-fromNowWatch.ResultChan(): t.Fatalf("unexpected event %v", event) case <-time.After(3 * time.Second): } }
func TestTriggers_manual(t *testing.T) { const namespace = "test-triggers-manual" _, clusterAdminKubeConfig, err := testserver.StartTestMaster() checkErr(t, err) clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) checkErr(t, err) clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) checkErr(t, err) _, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, namespace, "my-test-user") checkErr(t, err) osClient, kubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "my-test-user") checkErr(t, err) config := deploytest.OkDeploymentConfig(0) config.Namespace = namespace config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{ { Type: deployapi.DeploymentTriggerManual, }, } dc, err := osClient.DeploymentConfigs(namespace).Create(config) if err != nil { t.Fatalf("Couldn't create DeploymentConfig: %v %#v", err, config) } rcWatch, err := kubeClient.ReplicationControllers(namespace).Watch(labels.Everything(), fields.Everything(), dc.ResourceVersion) if err != nil { t.Fatalf("Couldn't subscribe to Deployments: %v", err) } defer rcWatch.Stop() retryErr := kclient.RetryOnConflict(wait.Backoff{Steps: maxUpdateRetries}, func() error { config, err := osClient.DeploymentConfigs(namespace).Generate(config.Name) if err != nil { return err } if config.Status.LatestVersion != 1 { t.Fatalf("Generated deployment should have version 1: %#v", config) } t.Logf("config(1): %#v", config) updatedConfig, err := osClient.DeploymentConfigs(namespace).Update(config) if err != nil { return err } t.Logf("config(2): %#v", updatedConfig) return nil }) if retryErr != nil { t.Fatal(err) } event := <-rcWatch.ResultChan() if e, a := watchapi.Added, event.Type; e != a { t.Fatalf("expected watch event type %s, got %s", e, a) } deployment := event.Object.(*kapi.ReplicationController) if e, a := config.Name, deployutil.DeploymentConfigNameFor(deployment); e != a { t.Fatalf("Expected deployment annotated with deploymentConfig '%s', got '%s'", e, a) } if e, a := 1, deployutil.DeploymentVersionFor(deployment); e != a { t.Fatalf("Deployment annotation version does not match: %#v", deployment) } }
func TestScopedProjectAccess(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } fullBobClient, _, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "bob") if err != nil { t.Fatalf("unexpected error: %v", err) } oneTwoBobClient, _, _, err := testutil.GetScopedClientForUser(clusterAdminClient, *clusterAdminClientConfig, "bob", []string{ scope.UserListScopedProjects, scope.ClusterRoleIndicator + "view:one", scope.ClusterRoleIndicator + "view:two", }) if err != nil { t.Fatalf("unexpected error: %v", err) } twoThreeBobClient, _, _, err := testutil.GetScopedClientForUser(clusterAdminClient, *clusterAdminClientConfig, "bob", []string{ scope.UserListScopedProjects, scope.ClusterRoleIndicator + "view:two", scope.ClusterRoleIndicator + "view:three", }) allBobClient, _, _, err := testutil.GetScopedClientForUser(clusterAdminClient, *clusterAdminClientConfig, "bob", []string{ scope.UserListScopedProjects, scope.ClusterRoleIndicator + "view:*", }) if err != nil { t.Fatalf("unexpected error: %v", err) } oneTwoWatch, err := oneTwoBobClient.Projects().Watch(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } twoThreeWatch, err := twoThreeBobClient.Projects().Watch(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } allWatch, err := allBobClient.Projects().Watch(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "one", "bob"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyAdd("one", allWatch, t) waitForOnlyAdd("one", oneTwoWatch, t) if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "two", "bob"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyAdd("two", allWatch, t) waitForOnlyAdd("two", oneTwoWatch, t) waitForOnlyAdd("two", twoThreeWatch, t) if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "three", "bob"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyAdd("three", allWatch, t) waitForOnlyAdd("three", twoThreeWatch, t) if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "four", "bob"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyAdd("four", allWatch, t) oneTwoProjects, err := oneTwoBobClient.Projects().List(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } if err := hasExactlyTheseProjects(oneTwoProjects, sets.NewString("one", "two")); err != nil { t.Error(err) } twoThreeProjects, err := twoThreeBobClient.Projects().List(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } if err := hasExactlyTheseProjects(twoThreeProjects, sets.NewString("two", "three")); err != nil { t.Error(err) } allProjects, err := allBobClient.Projects().List(kapi.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } if err := hasExactlyTheseProjects(allProjects, sets.NewString("one", "two", "three", "four")); err != nil { t.Error(err) } if err := fullBobClient.Projects().Delete("four"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyDelete("four", allWatch, t) if err := fullBobClient.Projects().Delete("three"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyDelete("three", allWatch, t) waitForOnlyDelete("three", twoThreeWatch, t) if err := fullBobClient.Projects().Delete("two"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyDelete("two", allWatch, t) waitForOnlyDelete("two", oneTwoWatch, t) waitForOnlyDelete("two", twoThreeWatch, t) if err := fullBobClient.Projects().Delete("one"); err != nil { t.Fatalf("unexpected error: %v", err) } waitForOnlyDelete("one", allWatch, t) waitForOnlyDelete("one", oneTwoWatch, t) }
func runStorageTest(t *testing.T, ns string, autoscalingVersion, batchVersion, extensionsVersion unversioned.GroupVersion) { etcdServer := testutil.RequireEtcd(t) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("unexpected error: %v", err) } keys := etcd.NewKeysAPI(etcdServer.Client) getGVKFromEtcd := func(prefix, name string) (*unversioned.GroupVersionKind, error) { key := path.Join(masterConfig.EtcdStorageConfig.KubernetesStoragePrefix, prefix, ns, name) resp, err := keys.Get(context.TODO(), key, nil) if err != nil { return nil, err } _, gvk, err := runtime.UnstructuredJSONScheme.Decode([]byte(resp.Node.Value), nil, nil) return gvk, err } // TODO: Set storage versions for API groups // masterConfig.EtcdStorageConfig.StorageVersions[autoscaling.GroupName] = autoscalingVersion.String() // masterConfig.EtcdStorageConfig.StorageVersions[batch.GroupName] = batchVersion.String() // masterConfig.EtcdStorageConfig.StorageVersions[extensions.GroupName] = extensionsVersion.String() clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } // create the containing project if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, ns, "admin"); err != nil { t.Fatalf("unexpected error creating the project: %v", err) } projectAdminClient, projectAdminKubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "admin") if err != nil { t.Fatalf("unexpected error getting project admin client: %v", err) } if err := testutil.WaitForPolicyUpdate(projectAdminClient, ns, "get", extensions.Resource("horizontalpodautoscalers"), true); err != nil { t.Fatalf("unexpected error waiting for policy update: %v", err) } jobTestcases := map[string]struct { creator kclient.JobInterface }{ "batch": {creator: projectAdminKubeClient.Batch().Jobs(ns)}, } for name, testcase := range jobTestcases { job := batch.Job{ ObjectMeta: kapi.ObjectMeta{Name: name + "-job"}, Spec: batch.JobSpec{ Template: kapi.PodTemplateSpec{ Spec: kapi.PodSpec{ RestartPolicy: kapi.RestartPolicyNever, Containers: []kapi.Container{{Name: "containername", Image: "containerimage"}}, }, }, }, } // Create a Job if _, err := testcase.creator.Create(&job); err != nil { t.Fatalf("%s: unexpected error creating Job: %v", name, err) } // Ensure it is persisted correctly if gvk, err := getGVKFromEtcd("jobs", job.Name); err != nil { t.Fatalf("%s: unexpected error reading Job: %v", name, err) } else if *gvk != batchVersion.WithKind("Job") { t.Fatalf("%s: expected api version %s in etcd, got %s reading Job", name, batchVersion, gvk) } // Ensure it is accessible from both APIs if _, err := projectAdminKubeClient.Batch().Jobs(ns).Get(job.Name); err != nil { t.Errorf("%s: Error reading Job from the batch client: %#v", name, err) } if _, err := projectAdminKubeClient.Extensions().Jobs(ns).Get(job.Name); err != nil { t.Errorf("%s: Error reading Job from the extensions client: %#v", name, err) } } hpaTestcases := map[string]struct { creator kclient.HorizontalPodAutoscalerInterface }{ "autoscaling": {creator: projectAdminKubeClient.Autoscaling().HorizontalPodAutoscalers(ns)}, "extensions": {creator: projectAdminKubeClient.Extensions().HorizontalPodAutoscalers(ns)}, } for name, testcase := range hpaTestcases { hpa := extensions.HorizontalPodAutoscaler{ ObjectMeta: kapi.ObjectMeta{Name: name + "-hpa"}, Spec: extensions.HorizontalPodAutoscalerSpec{ MaxReplicas: 1, ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "myrc", Subresource: "scale"}, }, } // Create an HPA if _, err := testcase.creator.Create(&hpa); err != nil { t.Fatalf("%s: unexpected error creating HPA: %v", name, err) } // Make sure it is persisted correctly if gvk, err := getGVKFromEtcd("horizontalpodautoscalers", hpa.Name); err != nil { t.Fatalf("%s: unexpected error reading HPA: %v", name, err) } else if *gvk != autoscalingVersion.WithKind("HorizontalPodAutoscaler") { t.Fatalf("%s: expected api version %s in etcd, got %s reading HPA", name, autoscalingVersion, gvk) } // Make sure it is available from both APIs if _, err := projectAdminKubeClient.Autoscaling().HorizontalPodAutoscalers(ns).Get(hpa.Name); err != nil { t.Errorf("%s: Error reading HPA.autoscaling from the autoscaling/v1 API: %#v", name, err) } if _, err := projectAdminKubeClient.Extensions().HorizontalPodAutoscalers(ns).Get(hpa.Name); err != nil { t.Errorf("%s: Error reading HPA.extensions from the extensions/v1beta1 API: %#v", name, err) } } }
func TestInvalidRoleRefs(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } bobClient, _, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "bob") if err != nil { t.Fatalf("unexpected error: %v", err) } aliceClient, _, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "alice") if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "foo", "bob"); err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "bar", "alice"); err != nil { t.Fatalf("unexpected error: %v", err) } roleName := "missing-role" if _, err := clusterAdminClient.ClusterRoles().Create(&authorizationapi.ClusterRole{ObjectMeta: kapi.ObjectMeta{Name: roleName}}); err != nil { t.Fatalf("unexpected error: %v", err) } modifyRole := &policy.RoleModificationOptions{RoleName: roleName, Users: []string{"someuser"}} // mess up rolebindings in "foo" modifyRole.RoleBindingAccessor = policy.NewLocalRoleBindingAccessor("foo", clusterAdminClient) if err := modifyRole.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } // mess up rolebindings in "bar" modifyRole.RoleBindingAccessor = policy.NewLocalRoleBindingAccessor("bar", clusterAdminClient) if err := modifyRole.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } // mess up clusterrolebindings modifyRole.RoleBindingAccessor = policy.NewClusterRoleBindingAccessor(clusterAdminClient) if err := modifyRole.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } // Orphan the rolebindings by deleting the role if err := clusterAdminClient.ClusterRoles().Delete(roleName); err != nil { t.Fatalf("unexpected error: %v", err) } // wait for evaluation errors to show up in both namespaces and at cluster scope if err := wait.PollImmediate(100*time.Millisecond, 10*time.Second, func() (bool, error) { review := &authorizationapi.ResourceAccessReview{Action: authorizationapi.Action{Verb: "get", Resource: "pods"}} review.Action.Namespace = "foo" if resp, err := clusterAdminClient.ResourceAccessReviews().Create(review); err != nil || resp.EvaluationError == "" { return false, err } review.Action.Namespace = "bar" if resp, err := clusterAdminClient.ResourceAccessReviews().Create(review); err != nil || resp.EvaluationError == "" { return false, err } review.Action.Namespace = "" if resp, err := clusterAdminClient.ResourceAccessReviews().Create(review); err != nil || resp.EvaluationError == "" { return false, err } return true, nil }); err != nil { t.Fatalf("unexpected error: %v", err) } // Make sure bob still sees his project (and only his project) if projects, err := bobClient.Projects().List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %v", err) } else if hasErr := hasExactlyTheseProjects(projects, sets.NewString("foo")); hasErr != nil { t.Error(hasErr) } // Make sure alice still sees her project (and only her project) if projects, err := aliceClient.Projects().List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %v", err) } else if hasErr := hasExactlyTheseProjects(projects, sets.NewString("bar")); hasErr != nil { t.Error(hasErr) } // Make sure cluster admin still sees all projects if projects, err := clusterAdminClient.Projects().List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %v", err) } else { projectNames := sets.NewString() for _, project := range projects.Items { projectNames.Insert(project.Name) } if !projectNames.HasAll("foo", "bar", "openshift-infra", "openshift", "default") { t.Errorf("Expected projects foo and bar, got %v", projectNames.List()) } } }
func TestAuthorizationSubjectAccessReviewAPIGroup(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } _, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "hammer-project", "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } // SAR honors API Group subjectAccessReviewTest{ description: "cluster admin told harold can get extensions.horizontalpodautoscalers in project hammer-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("hammer-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.Action{Verb: "get", Group: "extensions", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by rule in hammer-project", Namespace: "hammer-project", }, }.run(t) subjectAccessReviewTest{ description: "cluster admin told harold cannot get horizontalpodautoscalers (with no API group) in project hammer-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("hammer-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.Action{Verb: "get", Group: "", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "harold" cannot get horizontalpodautoscalers in project "hammer-project"`, Namespace: "hammer-project", }, }.run(t) subjectAccessReviewTest{ description: "cluster admin told harold cannot get horizontalpodautoscalers (with invalid API group) in project hammer-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("hammer-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.Action{Verb: "get", Group: "foo", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "harold" cannot get foo.horizontalpodautoscalers in project "hammer-project"`, Namespace: "hammer-project", }, }.run(t) subjectAccessReviewTest{ description: "cluster admin told harold cannot get horizontalpodautoscalers (with * API group) in project hammer-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("hammer-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ User: "******", Action: authorizationapi.Action{Verb: "get", Group: "*", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "harold" cannot get *.horizontalpodautoscalers in project "hammer-project"`, Namespace: "hammer-project", }, }.run(t) // SAR honors API Group for cluster admin self SAR subjectAccessReviewTest{ description: "cluster admin told they can get extensions.horizontalpodautoscalers in project hammer-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("any-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.Action{Verb: "get", Group: "extensions", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by cluster rule", Namespace: "any-project", }, }.run(t) subjectAccessReviewTest{ description: "cluster admin told they can get horizontalpodautoscalers (with no API group) in project any-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("any-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.Action{Verb: "get", Group: "", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by cluster rule", Namespace: "any-project", }, }.run(t) subjectAccessReviewTest{ description: "cluster admin told they can get horizontalpodautoscalers (with invalid API group) in project any-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("any-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.Action{Verb: "get", Group: "foo", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by cluster rule", Namespace: "any-project", }, }.run(t) subjectAccessReviewTest{ description: "cluster admin told they can get horizontalpodautoscalers (with * API group) in project any-project", localInterface: clusterAdminClient.LocalSubjectAccessReviews("any-project"), localReview: &authorizationapi.LocalSubjectAccessReview{ Action: authorizationapi.Action{Verb: "get", Group: "*", Resource: "horizontalpodautoscalers"}, }, response: authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: "allowed by cluster rule", Namespace: "any-project", }, }.run(t) }
func TestPodUpdateSCCEnforcement(t *testing.T) { testutil.RequireEtcd(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } projectName := "hammer-project" if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projectName, "harold"); err != nil { t.Fatalf("unexpected error: %v", err) } _, haroldKubeClient, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } if err := testserver.WaitForServiceAccounts(clusterAdminKubeClient, projectName, []string{"default"}); err != nil { t.Fatalf("unexpected error: %v", err) } // so cluster-admin can create privileged pods, but harold cannot. This means that harold should not be able // to update the privileged pods either, even if he lies about its privileged nature privilegedPod := &kapi.Pod{ ObjectMeta: kapi.ObjectMeta{Name: "unsafe"}, Spec: kapi.PodSpec{ Containers: []kapi.Container{ {Name: "first", Image: "something-innocuous"}, }, SecurityContext: &kapi.PodSecurityContext{ HostPID: true, }, }, } if _, err := haroldKubeClient.Pods(projectName).Create(privilegedPod); !kapierror.IsForbidden(err) { t.Fatalf("missing forbidden: %v", err) } actualPod, err := clusterAdminKubeClient.Pods(projectName).Create(privilegedPod) if err != nil { t.Fatalf("unexpected error: %v", err) } actualPod.Spec.Containers[0].Image = "something-nefarious" if _, err := haroldKubeClient.Pods(projectName).Update(actualPod); !kapierror.IsForbidden(err) { t.Fatalf("missing forbidden: %v", err) } // try to lie about the privileged nature actualPod.Spec.SecurityContext.HostPID = false if _, err := haroldKubeClient.Pods(projectName).Update(actualPod); err == nil { t.Fatalf("missing error: %v", err) } }
func TestAuthorizationResourceAccessReview(t *testing.T) { _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } haroldClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "hammer-project", "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } markClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "mallet-project", "mark") if err != nil { t.Fatalf("unexpected error: %v", err) } addValerie := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.ViewRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor("hammer-project", haroldClient), Users: []string{"valerie"}, } if err := addValerie.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } addEdgar := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.EditRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor("mallet-project", markClient), Users: []string{"edgar"}, } if err := addEdgar.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } requestWhoCanViewDeployments := &authorizationapi.ResourceAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "get", Resource: "deployments"}, } localRequestWhoCanViewDeployments := &authorizationapi.LocalResourceAccessReview{ Action: authorizationapi.AuthorizationAttributes{Verb: "get", Resource: "deployments"}, } { test := localResourceAccessReviewTest{ description: "who can view deployments in hammer by harold", clientInterface: haroldClient.LocalResourceAccessReviews("hammer-project"), review: localRequestWhoCanViewDeployments, response: authorizationapi.ResourceAccessReviewResponse{ Users: sets.NewString("harold", "valerie"), Groups: globalClusterAdminGroups, Namespace: "hammer-project", }, } test.response.Users.Insert(globalClusterAdminUsers.List()...) test.response.Groups.Insert("system:cluster-readers") test.run(t) } { test := localResourceAccessReviewTest{ description: "who can view deployments in mallet by mark", clientInterface: markClient.LocalResourceAccessReviews("mallet-project"), review: localRequestWhoCanViewDeployments, response: authorizationapi.ResourceAccessReviewResponse{ Users: sets.NewString("mark", "edgar"), Groups: globalClusterAdminGroups, Namespace: "mallet-project", }, } test.response.Users.Insert(globalClusterAdminUsers.List()...) test.response.Groups.Insert("system:cluster-readers") test.run(t) } // mark should not be able to make global access review requests { test := resourceAccessReviewTest{ description: "who can view deployments in all by mark", clientInterface: markClient.ResourceAccessReviews(), review: requestWhoCanViewDeployments, err: "cannot ", } test.run(t) } // a cluster-admin should be able to make global access review requests { test := resourceAccessReviewTest{ description: "who can view deployments in all by cluster-admin", clientInterface: clusterAdminClient.ResourceAccessReviews(), review: requestWhoCanViewDeployments, response: authorizationapi.ResourceAccessReviewResponse{ Users: globalClusterAdminUsers, Groups: globalClusterAdminGroups, }, } test.response.Groups.Insert("system:cluster-readers") test.run(t) } { if err := clusterAdminClient.ClusterRoles().Delete(bootstrappolicy.AdminRoleName); err != nil { t.Errorf("unexpected error: %v", err) } test := localResourceAccessReviewTest{ description: "who can view deployments in mallet by cluster-admin", clientInterface: clusterAdminClient.LocalResourceAccessReviews("mallet-project"), review: localRequestWhoCanViewDeployments, response: authorizationapi.ResourceAccessReviewResponse{ Users: sets.NewString("edgar"), Groups: globalClusterAdminGroups, Namespace: "mallet-project", }, } test.response.Users.Insert(globalClusterAdminUsers.List()...) test.response.Groups.Insert("system:cluster-readers") test.run(t) } }
func setupBuildStrategyTest(t *testing.T, includeControllers bool) (clusterAdminClient, projectAdminClient, projectEditorClient *client.Client) { testutil.RequireEtcd(t) namespace := testutil.Namespace() var clusterAdminKubeConfig string var err error if includeControllers { _, clusterAdminKubeConfig, err = testserver.StartTestMaster() } else { _, clusterAdminKubeConfig, err = testserver.StartTestMasterAPI() } if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err = testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } projectAdminClient, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, namespace, "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } projectEditorClient, _, _, err = testutil.GetClientForUser(*clusterAdminClientConfig, "joe") if err != nil { t.Fatalf("unexpected error: %v", err) } addJoe := &policy.RoleModificationOptions{ RoleNamespace: "", RoleName: bootstrappolicy.EditRoleName, RoleBindingAccessor: policy.NewLocalRoleBindingAccessor(namespace, projectAdminClient), Users: []string{"joe"}, } if err := addJoe.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } if err := testutil.WaitForPolicyUpdate(projectEditorClient, namespace, "create", buildapi.Resource(authorizationapi.DockerBuildResource), true); err != nil { t.Fatalf(err.Error()) } // we need a template that doesn't create service accounts or rolebindings so editors can create // pipeline buildconfig's successfully, so we're not using the standard jenkins template. // but we do need a template that creates a service named jenkins. template, err := testutil.GetTemplateFixture("../../examples/jenkins/master-slave/jenkins-master-template.json") if err != nil { t.Fatalf("unexpected error: %v", err) } // pipeline defaults expect to find a template named jenkins-ephemeral // in the openshift namespace. template.Name = "jenkins-ephemeral" template.Namespace = "openshift" _, err = clusterAdminClient.Templates("openshift").Create(template) if err != nil { t.Fatalf("Couldn't create jenkins template: %v", err) } return }
// TestOldLocalSubjectAccessReviewEndpoint checks to make sure that the old subject access review endpoint still functions properly // this is needed to support old docker registry images func TestOldLocalSubjectAccessReviewEndpoint(t *testing.T) { _, clusterAdminKubeConfig, err := testserver.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } haroldClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, "hammer-project", "harold") if err != nil { t.Fatalf("unexpected error: %v", err) } namespace := "hammer-project" // simple check { sar := &authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Verb: "get", Resource: "imagestreams/layers", }, } actualResponse := &authorizationapi.SubjectAccessReviewResponse{} err := haroldClient.Post().Namespace(namespace).Resource("subjectAccessReviews").Body(sar).Do().Into(actualResponse) if err != nil { t.Errorf("unexpected error: %v", err) } expectedResponse := &authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: `allowed by rule in hammer-project`, Namespace: namespace, } if (actualResponse.Namespace != expectedResponse.Namespace) || (actualResponse.Allowed != expectedResponse.Allowed) || (!strings.HasPrefix(actualResponse.Reason, expectedResponse.Reason)) { t.Errorf("review\n\t%#v\nexpected\n\t%#v\ngot\n\t%#v", sar, expectedResponse, actualResponse) } } // namespace forced to allowed namespace so we can't trick the server into leaking { sar := &authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Namespace: "sneaky-user", Verb: "get", Resource: "imagestreams/layers", }, } actualResponse := &authorizationapi.SubjectAccessReviewResponse{} err := haroldClient.Post().Namespace(namespace).Resource("subjectAccessReviews").Body(sar).Do().Into(actualResponse) if err != nil { t.Errorf("unexpected error: %v", err) } expectedResponse := &authorizationapi.SubjectAccessReviewResponse{ Allowed: true, Reason: `allowed by rule in hammer-project`, Namespace: namespace, } if (actualResponse.Namespace != expectedResponse.Namespace) || (actualResponse.Allowed != expectedResponse.Allowed) || (!strings.HasPrefix(actualResponse.Reason, expectedResponse.Reason)) { t.Errorf("review\n\t%#v\nexpected\n\t%#v\ngot\n\t%#v", sar, expectedResponse, actualResponse) } } // harold should be able to issue a self SAR against any project with the OLD policy { otherNamespace := "chisel-project" // we need a real project for this to make it past admission. // TODO, this is an information leaking problem. This admission plugin leaks knowledge of which projects exist via SARs if _, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, otherNamespace, "charlie"); err != nil { t.Fatalf("unexpected error: %v", err) } // remove the new permission for localSAR basicUserRole, err := clusterAdminClient.ClusterRoles().Get(bootstrappolicy.BasicUserRoleName) if err != nil { t.Fatalf("unexpected error: %v", err) } for i := range basicUserRole.Rules { basicUserRole.Rules[i].Resources.Delete("localsubjectaccessreviews") } if _, err := clusterAdminClient.ClusterRoles().Update(basicUserRole); err != nil { t.Fatalf("unexpected error: %v", err) } sar := &authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Verb: "get", Resource: "imagestreams/layers", }, } actualResponse := &authorizationapi.SubjectAccessReviewResponse{} err = haroldClient.Post().Namespace(otherNamespace).Resource("subjectAccessReviews").Body(sar).Do().Into(actualResponse) if err != nil { t.Errorf("unexpected error: %v", err) } expectedResponse := &authorizationapi.SubjectAccessReviewResponse{ Allowed: false, Reason: `User "harold" cannot get imagestreams/layers in project "chisel-project"`, Namespace: otherNamespace, } if (actualResponse.Namespace != expectedResponse.Namespace) || (actualResponse.Allowed != expectedResponse.Allowed) || (!strings.HasPrefix(actualResponse.Reason, expectedResponse.Reason)) { t.Errorf("review\n\t%#v\nexpected\n\t%#v\ngot\n\t%#v", sar, expectedResponse, actualResponse) } } }
func TestScopeEscalations(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } projectName := "hammer-project" userName := "******" haroldClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projectName, userName) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := haroldClient.Builds(projectName).List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %v", err) } haroldUser, err := haroldClient.Users().Get("~") if err != nil { t.Fatalf("unexpected error: %v", err) } nonEscalatingEditToken := &oauthapi.OAuthAccessToken{ ObjectMeta: kapi.ObjectMeta{Name: "non-escalating-edit-plus-some-padding-here-to-make-the-limit"}, ClientName: origin.OpenShiftCLIClientID, ExpiresIn: 200, Scopes: []string{scope.ClusterRoleIndicator + "edit:*"}, UserName: userName, UserUID: string(haroldUser.UID), } if _, err := clusterAdminClient.OAuthAccessTokens().Create(nonEscalatingEditToken); err != nil { t.Fatalf("unexpected error: %v", err) } nonEscalatingEditConfig := clientcmd.AnonymousClientConfig(clusterAdminClientConfig) nonEscalatingEditConfig.BearerToken = nonEscalatingEditToken.Name nonEscalatingEditClient, err := kclientset.NewForConfig(&nonEscalatingEditConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := nonEscalatingEditClient.Secrets(projectName).List(kapi.ListOptions{}); !kapierrors.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } escalatingEditToken := &oauthapi.OAuthAccessToken{ ObjectMeta: kapi.ObjectMeta{Name: "escalating-edit-plus-some-padding-here-to-make-the-limit"}, ClientName: origin.OpenShiftCLIClientID, ExpiresIn: 200, Scopes: []string{scope.ClusterRoleIndicator + "edit:*:!"}, UserName: userName, UserUID: string(haroldUser.UID), } if _, err := clusterAdminClient.OAuthAccessTokens().Create(escalatingEditToken); err != nil { t.Fatalf("unexpected error: %v", err) } escalatingEditConfig := clientcmd.AnonymousClientConfig(clusterAdminClientConfig) escalatingEditConfig.BearerToken = escalatingEditToken.Name escalatingEditClient, err := kclientset.NewForConfig(&escalatingEditConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := escalatingEditClient.Secrets(projectName).List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %v", err) } }
func TestDeployScale(t *testing.T) { const namespace = "test-deploy-scale" testutil.RequireEtcd(t) _, clusterAdminKubeConfig, err := testserver.StartTestMaster() checkErr(t, err) clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) checkErr(t, err) clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) checkErr(t, err) _, err = testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, namespace, "my-test-user") checkErr(t, err) osClient, _, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, "my-test-user") checkErr(t, err) config := deploytest.OkDeploymentConfig(0) config.Spec.Triggers = []deployapi.DeploymentTriggerPolicy{} config.Spec.Replicas = 1 dc, err := osClient.DeploymentConfigs(namespace).Create(config) if err != nil { t.Fatalf("Couldn't create DeploymentConfig: %v %#v", err, config) } condition := func() (bool, error) { config, err := osClient.DeploymentConfigs(namespace).Get(dc.Name) if err != nil { return false, nil } return deployutil.HasSynced(config), nil } if err := wait.PollImmediate(500*time.Millisecond, 10*time.Second, condition); err != nil { t.Fatalf("Deployment config never synced: %v", err) } scale, err := osClient.DeploymentConfigs(namespace).GetScale(config.Name) if err != nil { t.Fatalf("Couldn't get DeploymentConfig scale: %v", err) } if scale.Spec.Replicas != 1 { t.Fatalf("Expected scale.spec.replicas=1, got %#v", scale) } scaleUpdate := deployapi.ScaleFromConfig(dc) scaleUpdate.Spec.Replicas = 3 updatedScale, err := osClient.DeploymentConfigs(namespace).UpdateScale(scaleUpdate) if err != nil { // If this complains about "Scale" not being registered in "v1", check the kind overrides in the API registration in SubresourceGroupVersionKind t.Fatalf("Couldn't update DeploymentConfig scale to %#v: %v", scaleUpdate, err) } if updatedScale.Spec.Replicas != 3 { t.Fatalf("Expected scale.spec.replicas=3, got %#v", scale) } persistedScale, err := osClient.DeploymentConfigs(namespace).GetScale(config.Name) if err != nil { t.Fatalf("Couldn't get DeploymentConfig scale: %v", err) } if persistedScale.Spec.Replicas != 3 { t.Fatalf("Expected scale.spec.replicas=3, got %#v", scale) } }
func TestScopedTokens(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } projectName := "hammer-project" userName := "******" haroldClient, err := testserver.CreateNewProject(clusterAdminClient, *clusterAdminClientConfig, projectName, userName) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := haroldClient.Builds(projectName).List(kapi.ListOptions{}); err != nil { t.Fatalf("unexpected error: %v", err) } haroldUser, err := haroldClient.Users().Get("~") if err != nil { t.Fatalf("unexpected error: %v", err) } whoamiOnlyToken := &oauthapi.OAuthAccessToken{ ObjectMeta: kapi.ObjectMeta{Name: "whoami-token-plus-some-padding-here-to-make-the-limit"}, ClientName: origin.OpenShiftCLIClientID, ExpiresIn: 200, Scopes: []string{scope.UserInfo}, UserName: userName, UserUID: string(haroldUser.UID), } if _, err := clusterAdminClient.OAuthAccessTokens().Create(whoamiOnlyToken); err != nil { t.Fatalf("unexpected error: %v", err) } whoamiConfig := clientcmd.AnonymousClientConfig(clusterAdminClientConfig) whoamiConfig.BearerToken = whoamiOnlyToken.Name whoamiClient, err := client.New(&whoamiConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := whoamiClient.Builds(projectName).List(kapi.ListOptions{}); !kapierrors.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } user, err := whoamiClient.Users().Get("~") if err != nil { t.Fatalf("unexpected error: %v", err) } if user.Name != userName { t.Fatalf("expected %v, got %v", userName, user.Name) } // try to impersonate a service account using this token whoamiConfig.Impersonate = serviceaccount.MakeUsername(projectName, "default") impersonatingClient, err := client.New(&whoamiConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } impersonatedUser, err := impersonatingClient.Users().Get("~") if !kapierrors.IsForbidden(err) { t.Fatalf("missing error: %v got user %#v", err, impersonatedUser) } }