-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Make List Projects authorization aware #971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # Generates 500 projects | ||
|
|
||
| set -o errexit | ||
| set -o nounset | ||
| set -o pipefail | ||
|
|
||
| #!/bin/bash | ||
| for i in {1..500} | ||
| do | ||
| openshift ex new-project projects-${i} | ||
| done |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -60,6 +60,7 @@ import ( | |
| clientregistry "github.com/openshift/origin/pkg/oauth/registry/client" | ||
| clientauthorizationregistry "github.com/openshift/origin/pkg/oauth/registry/clientauthorization" | ||
| oauthetcd "github.com/openshift/origin/pkg/oauth/registry/etcd" | ||
| projectauth "github.com/openshift/origin/pkg/project/auth" | ||
| projectregistry "github.com/openshift/origin/pkg/project/registry/project" | ||
| routeetcd "github.com/openshift/origin/pkg/route/registry/etcd" | ||
| routeregistry "github.com/openshift/origin/pkg/route/registry/route" | ||
|
|
@@ -114,6 +115,8 @@ type MasterConfig struct { | |
| AuthorizationAttributeBuilder authorizer.AuthorizationAttributeBuilder | ||
| MasterAuthorizationNamespace string | ||
|
|
||
| ProjectAuthorizationCache *projectauth.AuthorizationCache | ||
|
|
||
| // Map requests to contexts | ||
| RequestContextMapper kapi.RequestContextMapper | ||
|
|
||
|
|
@@ -188,6 +191,15 @@ func (c *MasterConfig) KubeClient() *kclient.Client { | |
| return c.kubeClient | ||
| } | ||
|
|
||
| // PolicyClient returns the policy client object | ||
| // It must have the following capabilities: | ||
| // list, watch all policyBindings in all namespaces | ||
| // list, watch all policies in all namespaces | ||
| // create resourceAccessReviews in all namespaces | ||
| func (c *MasterConfig) PolicyClient() *osclient.Client { | ||
| return c.osClient | ||
| } | ||
|
|
||
| // DeploymentClient returns the deployment client object | ||
| func (c *MasterConfig) DeploymentClient() *kclient.Client { | ||
| return c.kubeClient | ||
|
|
@@ -288,7 +300,7 @@ func (c *MasterConfig) InstallProtectedAPI(container *restful.Container) []strin | |
|
|
||
| "routes": routeregistry.NewREST(routeEtcd), | ||
|
|
||
| "projects": projectregistry.NewREST(kclient.Namespaces()), | ||
| "projects": projectregistry.NewREST(kclient.Namespaces(), c.ProjectAuthorizationCache), | ||
|
|
||
| "userIdentityMappings": useridentitymapping.NewREST(userEtcd), | ||
| "users": userregistry.NewREST(userEtcd), | ||
|
|
@@ -366,8 +378,6 @@ func initAPIVersionRoute(root *restful.WebService, version string) { | |
| func (c *MasterConfig) Run(protected []APIInstaller, unprotected []APIInstaller) { | ||
| var extra []string | ||
|
|
||
| c.ensureComponentAuthorizationRules() | ||
|
|
||
| safe := kmaster.NewHandlerContainer(http.NewServeMux()) | ||
| open := kmaster.NewHandlerContainer(http.NewServeMux()) | ||
|
|
||
|
|
@@ -437,6 +447,14 @@ func (c *MasterConfig) Run(protected []APIInstaller, unprotected []APIInstaller) | |
|
|
||
| // Attempt to verify the server came up for 20 seconds (100 tries * 100ms, 100ms timeout per try) | ||
| cmdutil.WaitForSuccessfulDial("tcp", c.MasterBindAddr, 100*time.Millisecond, 100*time.Millisecond, 100) | ||
|
|
||
| // Attempt to create the required policy rules now, and then stick in a forever loop to make sure they are always available | ||
| c.ensureMasterAuthorizationNamespace() | ||
| c.ensureComponentAuthorizationRules() | ||
| go util.Forever(func() { | ||
| c.ensureMasterAuthorizationNamespace() | ||
| c.ensureComponentAuthorizationRules() | ||
| }, 10*time.Second) | ||
| } | ||
|
|
||
| // getRequestContextMapper returns a mapper from requests to contexts, initializing it if needed | ||
|
|
@@ -447,6 +465,21 @@ func (c *MasterConfig) getRequestContextMapper() kapi.RequestContextMapper { | |
| return c.RequestContextMapper | ||
| } | ||
|
|
||
| // ensureMasterAuthorizationNamespace is called as part of global policy initialization to ensure master namespace exists | ||
| func (c *MasterConfig) ensureMasterAuthorizationNamespace() { | ||
|
|
||
| // ensure that master namespace actually exists | ||
| namespace, err := c.KubeClient().Namespaces().Get(c.MasterAuthorizationNamespace) | ||
| if err != nil { | ||
| namespace = &kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: c.MasterAuthorizationNamespace}} | ||
| kapi.FillObjectMetaSystemFields(api.NewContext(), &namespace.ObjectMeta) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Boo, hiss, this is why we have registries.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we cant depend on them if the namespace is managed by an external kube process. this is less boo-hiss in my book than how the policy stuff is stored. |
||
| _, err = c.KubeClient().Namespaces().Create(namespace) | ||
| if err != nil { | ||
| glog.Errorf("Error creating namespace: %v due to %v\n", namespace, err) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // ensureComponentAuthorizationRules initializes the global policies | ||
| func (c *MasterConfig) ensureComponentAuthorizationRules() { | ||
| registry := authorizationetcd.New(c.EtcdHelper) | ||
|
|
@@ -519,6 +552,13 @@ func forbidden(reason string, w http.ResponseWriter, req *http.Request) { | |
| fmt.Fprintf(w, "Forbidden: %q %s", req.RequestURI, reason) | ||
| } | ||
|
|
||
| // RunProjectAuthorizationCache starts the project authorization cache | ||
| func (c *MasterConfig) RunProjectAuthorizationCache() { | ||
| // TODO: look at exposing a configuration option in future to control how often we run this loop | ||
| period := 1 * time.Second | ||
| c.ProjectAuthorizationCache.Run(period) | ||
| } | ||
|
|
||
| // RunAssetServer starts the asset server for the OpenShift UI. | ||
| func (c *MasterConfig) RunAssetServer() { | ||
| // TODO use version.Get().GitCommit as an etag cache header | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sanity check - this is stored in etcd if it doesn't exist, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, this is what generates what is stored in etcd. its buggy because it is not validated yet, and goes direct to registry.