Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions examples/project-spawner/project-spawner.sh
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
2 changes: 2 additions & 0 deletions pkg/authorization/authorizer/authorizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ func GetBootstrapPolicy(masterNamespace string) *authorizationapi.Policy {
Name: authorizationapi.PolicyName,
Namespace: masterNamespace,
CreationTimestamp: util.Now(),
UID: util.NewUUID(),
Copy link
Contributor

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?

Copy link
Member Author

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.

},
LastModified: util.Now(),
Roles: map[string]authorizationapi.Role{
Expand Down Expand Up @@ -482,6 +483,7 @@ func GetBootstrapPolicyBinding(masterNamespace string) *authorizationapi.PolicyB
Name: masterNamespace,
Namespace: masterNamespace,
CreationTimestamp: util.Now(),
UID: util.NewUUID(),
},
LastModified: util.Now(),
PolicyRef: kapi.ObjectReference{Namespace: masterNamespace},
Expand Down
46 changes: 43 additions & 3 deletions pkg/cmd/server/origin/master.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -114,6 +115,8 @@ type MasterConfig struct {
AuthorizationAttributeBuilder authorizer.AuthorizationAttributeBuilder
MasterAuthorizationNamespace string

ProjectAuthorizationCache *projectauth.AuthorizationCache

// Map requests to contexts
RequestContextMapper kapi.RequestContextMapper

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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())

Expand Down Expand Up @@ -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
Expand All @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boo, hiss, this is why we have registries.

Copy link
Member Author

Choose a reason for hiding this comment

The 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)
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/openshift/origin/pkg/authorization/authorizer"
authorizationetcd "github.com/openshift/origin/pkg/authorization/registry/etcd"
"github.com/openshift/origin/pkg/authorization/rulevalidation"
projectauth "github.com/openshift/origin/pkg/project/auth"

"github.com/openshift/origin/pkg/auth/group"
"github.com/openshift/origin/pkg/cmd/flagtypes"
Expand Down Expand Up @@ -501,6 +502,13 @@ func start(cfg *config, args []string) error {

osmaster.BuildClients()

osmaster.ProjectAuthorizationCache = projectauth.NewAuthorizationCache(
projectauth.NewReviewer(osmaster.PolicyClient()),
osmaster.KubeClient().Namespaces(),
osmaster.PolicyClient(),
osmaster.PolicyClient(),
osmaster.MasterAuthorizationNamespace)

// Default to a session authenticator (for browsers), and a basicauth authenticator (for clients responding to WWW-Authenticate challenges)
defaultAuthRequestHandlers := strings.Join([]string{
string(origin.AuthRequestHandlerSession),
Expand Down Expand Up @@ -599,6 +607,7 @@ func start(cfg *config, args []string) error {
osmaster.RunDeploymentConfigController()
osmaster.RunDeploymentConfigChangeController()
osmaster.RunDeploymentImageChangeTriggerController()
osmaster.RunProjectAuthorizationCache()

existingKubeClient = osmaster.KubeClient()
}
Expand Down
Loading