Skip to content

Commit d01bfa4

Browse files
committed
create policy cache
1 parent 7eb851c commit d01bfa4

File tree

3 files changed

+152
-8
lines changed

3 files changed

+152
-8
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package cache
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"time"
7+
8+
kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
9+
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
10+
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
11+
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
12+
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
13+
14+
authorizationapi "github.com/openshift/origin/pkg/authorization/api"
15+
policyregistry "github.com/openshift/origin/pkg/authorization/registry/policy"
16+
bindingregistry "github.com/openshift/origin/pkg/authorization/registry/policybinding"
17+
)
18+
19+
// PolicyCache maintains a cache of PolicyRules
20+
type PolicyCache struct {
21+
policyBindingIndexer cache.Indexer
22+
policyIndexer cache.Indexer
23+
24+
bindingRegistry bindingregistry.Registry
25+
policyRegistry policyregistry.Registry
26+
27+
keyFunc cache.KeyFunc
28+
}
29+
30+
// TODO: Eliminate listWatch when this merges upstream: https://github.com/GoogleCloudPlatform/kubernetes/pull/4453
31+
type listFunc func() (runtime.Object, error)
32+
type watchFunc func(resourceVersion string) (watch.Interface, error)
33+
type listWatch struct {
34+
listFunc listFunc
35+
watchFunc watchFunc
36+
}
37+
38+
func (lw *listWatch) List() (runtime.Object, error) {
39+
return lw.listFunc()
40+
}
41+
42+
func (lw *listWatch) Watch(resourceVersion string) (watch.Interface, error) {
43+
return lw.watchFunc(resourceVersion)
44+
}
45+
46+
// NewPolicyCache creates a new PolicyCache. You cannot use a normal client, because you don't want policy guarding the policy from the authorizer
47+
func NewPolicyCache(bindingRegistry bindingregistry.Registry, policyRegistry policyregistry.Registry) *PolicyCache {
48+
result := &PolicyCache{
49+
policyIndexer: cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}),
50+
policyBindingIndexer: cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}),
51+
52+
keyFunc: cache.MetaNamespaceKeyFunc,
53+
54+
bindingRegistry: bindingRegistry,
55+
policyRegistry: policyRegistry,
56+
}
57+
return result
58+
}
59+
60+
// Run begins watching and synchronizing the cache
61+
func (c *PolicyCache) Run(period time.Duration) {
62+
ctx := kapi.WithNamespace(kapi.NewContext(), kapi.NamespaceAll)
63+
64+
policyBindingReflector := cache.NewReflector(
65+
&listWatch{
66+
listFunc: func() (runtime.Object, error) {
67+
return c.bindingRegistry.ListPolicyBindings(ctx, labels.Everything(), labels.Everything())
68+
},
69+
watchFunc: func(resourceVersion string) (watch.Interface, error) {
70+
return c.bindingRegistry.WatchPolicyBindings(ctx, labels.Everything(), labels.Everything(), resourceVersion)
71+
},
72+
},
73+
&authorizationapi.PolicyBinding{},
74+
c.policyBindingIndexer,
75+
)
76+
policyBindingReflector.Run()
77+
78+
policyReflector := cache.NewReflector(
79+
&listWatch{
80+
listFunc: func() (runtime.Object, error) {
81+
return c.policyRegistry.ListPolicies(ctx, labels.Everything(), labels.Everything())
82+
},
83+
watchFunc: func(resourceVersion string) (watch.Interface, error) {
84+
return c.policyRegistry.WatchPolicies(ctx, labels.Everything(), labels.Everything(), resourceVersion)
85+
},
86+
},
87+
&authorizationapi.Policy{},
88+
c.policyIndexer,
89+
)
90+
policyReflector.Run()
91+
}
92+
93+
// GetPolicy retrieves a specific policy. It conforms to rulevalidation.PolicyGetter.
94+
func (c *PolicyCache) GetPolicy(ctx kapi.Context, name string) (*authorizationapi.Policy, error) {
95+
namespace, exists := kapi.NamespaceFrom(ctx)
96+
if !exists {
97+
return nil, errors.New("no namespace found")
98+
}
99+
100+
keyObj := &authorizationapi.Policy{ObjectMeta: kapi.ObjectMeta{Namespace: namespace, Name: name}}
101+
key, _ := c.keyFunc(keyObj)
102+
103+
policy, exists, err := c.policyIndexer.GetByKey(key)
104+
if err != nil {
105+
return nil, err
106+
}
107+
if !exists {
108+
return nil, fmt.Errorf("%v not found", key)
109+
}
110+
111+
return policy.(*authorizationapi.Policy), nil
112+
}
113+
114+
// ListPolicyBindings obtains list of policyBindings that match a selector. It conforms to rulevalidation.BindingLister
115+
func (c *PolicyCache) ListPolicyBindings(ctx kapi.Context, labels, fields labels.Selector) (*authorizationapi.PolicyBindingList, error) {
116+
namespace, exists := kapi.NamespaceFrom(ctx)
117+
if !exists {
118+
return nil, errors.New("no namespace found")
119+
}
120+
121+
bindings, err := c.policyBindingIndexer.Index("namespace", &authorizationapi.PolicyBinding{ObjectMeta: kapi.ObjectMeta{Namespace: namespace}})
122+
if err != nil {
123+
return nil, err
124+
}
125+
126+
ret := &authorizationapi.PolicyBindingList{}
127+
for i := range bindings {
128+
ret.Items = append(ret.Items, *bindings[i].(*authorizationapi.PolicyBinding))
129+
}
130+
131+
return ret, nil
132+
}

pkg/cmd/server/origin/master.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import (
7575

7676
authorizationapi "github.com/openshift/origin/pkg/authorization/api"
7777
"github.com/openshift/origin/pkg/authorization/authorizer"
78+
policycache "github.com/openshift/origin/pkg/authorization/cache"
7879
authorizationetcd "github.com/openshift/origin/pkg/authorization/registry/etcd"
7980
policyregistry "github.com/openshift/origin/pkg/authorization/registry/policy"
8081
policybindingregistry "github.com/openshift/origin/pkg/authorization/registry/policybinding"
@@ -115,6 +116,7 @@ type MasterConfig struct {
115116
AuthorizationAttributeBuilder authorizer.AuthorizationAttributeBuilder
116117
MasterAuthorizationNamespace string
117118

119+
PolicyCache *policycache.PolicyCache
118120
ProjectAuthorizationCache *projectauth.AuthorizationCache
119121

120122
// Map requests to contexts
@@ -559,6 +561,11 @@ func (c *MasterConfig) RunProjectAuthorizationCache() {
559561
c.ProjectAuthorizationCache.Run(period)
560562
}
561563

564+
// RunPolicyCache starts the policy cache
565+
func (c *MasterConfig) RunPolicyCache() {
566+
c.PolicyCache.Run(10 * time.Second)
567+
}
568+
562569
// RunAssetServer starts the asset server for the OpenShift UI.
563570
func (c *MasterConfig) RunAssetServer() {
564571
// TODO use version.Get().GitCommit as an etag cache header

pkg/cmd/server/start.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"github.com/openshift/origin/pkg/auth/authenticator/request/unionrequest"
3939
"github.com/openshift/origin/pkg/auth/authenticator/request/x509request"
4040
"github.com/openshift/origin/pkg/authorization/authorizer"
41+
policycache "github.com/openshift/origin/pkg/authorization/cache"
4142
authorizationetcd "github.com/openshift/origin/pkg/authorization/registry/etcd"
4243
"github.com/openshift/origin/pkg/authorization/rulevalidation"
4344
projectauth "github.com/openshift/origin/pkg/project/auth"
@@ -367,11 +368,9 @@ func start(cfg *config, args []string) error {
367368

368369
EtcdHelper: etcdHelper,
369370

370-
AdmissionControl: admit.NewAlwaysAdmit(),
371-
Authorizer: newAuthorizer(etcdHelper, masterAuthorizationNamespace),
372-
AuthorizationAttributeBuilder: newAuthorizationAttributeBuilder(requestContextMapper),
373-
MasterAuthorizationNamespace: masterAuthorizationNamespace,
374-
RequestContextMapper: requestContextMapper,
371+
AdmissionControl: admit.NewAlwaysAdmit(),
372+
MasterAuthorizationNamespace: masterAuthorizationNamespace,
373+
RequestContextMapper: requestContextMapper,
375374

376375
ImageFor: imageResolverFn,
377376
}
@@ -502,6 +501,13 @@ func start(cfg *config, args []string) error {
502501

503502
osmaster.BuildClients()
504503

504+
authorizationEtcd := authorizationetcd.New(etcdHelper)
505+
osmaster.PolicyCache = policycache.NewPolicyCache(authorizationEtcd, authorizationEtcd)
506+
osmaster.Authorizer = newAuthorizer(osmaster.PolicyCache, masterAuthorizationNamespace)
507+
osmaster.AuthorizationAttributeBuilder = newAuthorizationAttributeBuilder(requestContextMapper)
508+
// the policy cache must start before you attempt to start any other components
509+
osmaster.RunPolicyCache()
510+
505511
osmaster.ProjectAuthorizationCache = projectauth.NewAuthorizationCache(
506512
projectauth.NewReviewer(osmaster.PolicyClient()),
507513
osmaster.KubeClient().Namespaces(),
@@ -653,9 +659,8 @@ func start(cfg *config, args []string) error {
653659
return nil
654660
}
655661

656-
func newAuthorizer(etcdHelper tools.EtcdHelper, masterAuthorizationNamespace string) authorizer.Authorizer {
657-
authorizationEtcd := authorizationetcd.New(etcdHelper)
658-
authorizer := authorizer.NewAuthorizer(masterAuthorizationNamespace, rulevalidation.NewDefaultRuleResolver(authorizationEtcd, authorizationEtcd))
662+
func newAuthorizer(policyCache *policycache.PolicyCache, masterAuthorizationNamespace string) authorizer.Authorizer {
663+
authorizer := authorizer.NewAuthorizer(masterAuthorizationNamespace, rulevalidation.NewDefaultRuleResolver(policyCache, policyCache))
659664
return authorizer
660665
}
661666

0 commit comments

Comments
 (0)