Skip to content

Commit 965e3ea

Browse files
author
Jim Minter
committed
template broker should use SAR, not impersonation
1 parent 9fbc432 commit 965e3ea

40 files changed

+894
-350
lines changed

pkg/authorization/authorizer/subjects_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func TestSubjects(t *testing.T) {
4848
"system:kube-scheduler",
4949
"system:serviceaccount:openshift-infra:build-controller",
5050
"system:serviceaccount:openshift-infra:deployer-controller",
51+
"system:serviceaccount:openshift-infra:template-instance-controller",
5152
),
5253
expectedGroups: sets.NewString("RootUsers", "system:cluster-admins", "system:cluster-readers", "system:masters", "system:nodes"),
5354
}

pkg/authorization/util/util.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package util
2+
3+
import (
4+
"errors"
5+
6+
kerrors "k8s.io/apimachinery/pkg/api/errors"
7+
"k8s.io/apimachinery/pkg/runtime/schema"
8+
"k8s.io/apiserver/pkg/authentication/user"
9+
"k8s.io/kubernetes/pkg/apis/authorization"
10+
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion"
11+
)
12+
13+
// AddUserToSAR adds the requisite user information to a SubjectAccessReview.
14+
// It returns the modified SubjectAccessReview.
15+
func AddUserToSAR(user user.Info, sar *authorization.SubjectAccessReview) *authorization.SubjectAccessReview {
16+
sar.Spec.User = user.GetName()
17+
copy(sar.Spec.Groups, user.GetGroups())
18+
sar.Spec.Extra = map[string]authorization.ExtraValue{}
19+
20+
for k, v := range user.GetExtra() {
21+
sar.Spec.Extra[k] = authorization.ExtraValue(v)
22+
}
23+
24+
return sar
25+
}
26+
27+
// Authorize verifies that a given user is permitted to carry out a given
28+
// action. If this cannot be determined, or if the user is not permitted, an
29+
// error is returned.
30+
func Authorize(sarClient internalversion.SubjectAccessReviewInterface, user user.Info, resourceAttributes *authorization.ResourceAttributes) error {
31+
sar := AddUserToSAR(user, &authorization.SubjectAccessReview{
32+
Spec: authorization.SubjectAccessReviewSpec{
33+
ResourceAttributes: resourceAttributes,
34+
},
35+
})
36+
37+
resp, err := sarClient.Create(sar)
38+
if err == nil && resp != nil && resp.Status.Allowed {
39+
return nil
40+
}
41+
42+
if err == nil {
43+
err = errors.New(resp.Status.Reason)
44+
}
45+
return kerrors.NewForbidden(schema.GroupResource{Group: resourceAttributes.Group, Resource: resourceAttributes.Resource}, resourceAttributes.Name, err)
46+
}

pkg/client/cache/index.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ import (
77
buildutil "github.com/openshift/origin/pkg/build/util"
88
deployapi "github.com/openshift/origin/pkg/deploy/api"
99
imageapi "github.com/openshift/origin/pkg/image/api"
10-
templateapi "github.com/openshift/origin/pkg/template/api"
1110
)
1211

1312
const (
1413
ImageStreamReferenceIndex = "imagestreamref"
15-
TemplateUIDIndex = "templateuid"
1614
)
1715

1816
// ImageStreamReferenceIndexFunc is a default index function that indexes based on image stream references.
@@ -75,7 +73,3 @@ func ImageStreamReferenceIndexFunc(obj interface{}) ([]string, error) {
7573
}
7674
return nil, fmt.Errorf("image stream reference index not implemented for %#v", obj)
7775
}
78-
79-
func TemplateUIDIndexFunc(obj interface{}) ([]string, error) {
80-
return []string{string(obj.(*templateapi.Template).UID)}, nil
81-
}

pkg/client/cache/template.go

Lines changed: 0 additions & 49 deletions
This file was deleted.

pkg/cmd/server/bootstrappolicy/constants.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const (
6262
RegistryViewerRoleName = "registry-viewer"
6363
RegistryEditorRoleName = "registry-editor"
6464

65-
TemplateServiceBrokerClientRoleName = "templateservicebroker-client"
65+
TemplateServiceBrokerClientRoleName = "system:openshift:templateservicebroker-client"
6666

6767
BuildStrategyDockerRoleName = "system:build-strategy-docker"
6868
BuildStrategyCustomRoleName = "system:build-strategy-custom"

pkg/cmd/server/bootstrappolicy/controller_policy.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@ func init() {
9292
eventsRule(),
9393
},
9494
})
95+
96+
// template-instance-controller
97+
addControllerRole(rbac.ClusterRole{
98+
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + InfraTemplateInstanceControllerServiceAccountName},
99+
Rules: []rbac.PolicyRule{
100+
rbac.NewRule("create").Groups(kAuthzGroup).Resources("subjectaccessreviews").RuleOrDie(),
101+
rbac.NewRule("get", "list", "watch").Groups(templateGroup).Resources("subjectaccessreviews").RuleOrDie(),
102+
rbac.NewRule("update").Groups(templateGroup).Resources("templateinstances/status").RuleOrDie(),
103+
},
104+
})
105+
106+
controllerRoleBindings = append(controllerRoleBindings,
107+
rbac.NewClusterBinding(EditRoleName).SAs(DefaultOpenShiftInfraNamespace, InfraTemplateInstanceControllerServiceAccountName).BindingOrDie())
95108
}
96109

97110
// ControllerRoles returns the cluster roles used by controllers

pkg/cmd/server/bootstrappolicy/infra_sa_policy.go

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ import (
66
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
77
"k8s.io/apimachinery/pkg/util/sets"
88
kapi "k8s.io/kubernetes/pkg/api"
9+
"k8s.io/kubernetes/pkg/apis/authorization"
910
"k8s.io/kubernetes/pkg/apis/certificates"
1011
"k8s.io/kubernetes/pkg/apis/extensions"
1112
"k8s.io/kubernetes/pkg/apis/storage"
1213

13-
// we need the conversions registered for our init block
1414
authorizationapi "github.com/openshift/origin/pkg/authorization/api"
15-
_ "github.com/openshift/origin/pkg/authorization/api/install"
1615
authorizationapiv1 "github.com/openshift/origin/pkg/authorization/api/v1"
1716
buildapi "github.com/openshift/origin/pkg/build/api"
1817
deployapi "github.com/openshift/origin/pkg/deploy/api"
1918
imageapi "github.com/openshift/origin/pkg/image/api"
19+
templateapi "github.com/openshift/origin/pkg/template/api"
2020

2121
// we need the conversions registered for our init block
2222
_ "github.com/openshift/origin/pkg/authorization/api/install"
@@ -56,6 +56,16 @@ const (
5656

5757
InfraNodeBootstrapServiceAccountName = "node-bootstrapper"
5858
NodeBootstrapRoleName = "system:node-bootstrapper"
59+
60+
// template instance controller watches for TemplateInstance object creation
61+
// and instantiates templates as a result.
62+
InfraTemplateInstanceControllerServiceAccountName = "template-instance-controller"
63+
64+
// template service broker is an open service broker-compliant API
65+
// implementation which serves up OpenShift templates. It uses the
66+
// TemplateInstance backend for most of the heavy lifting.
67+
InfraTemplateServiceBrokerServiceAccountName = "template-service-broker"
68+
TemplateServiceBrokerControllerRoleName = "system:openshift:template-service-broker"
5969
)
6070

6171
type InfraServiceAccounts struct {
@@ -588,4 +598,45 @@ func init() {
588598
panic(err)
589599
}
590600

601+
err = InfraSAs.addServiceAccount(
602+
InfraTemplateServiceBrokerServiceAccountName,
603+
authorizationapi.ClusterRole{
604+
ObjectMeta: metav1.ObjectMeta{
605+
Name: TemplateServiceBrokerControllerRoleName,
606+
},
607+
Rules: []authorizationapi.PolicyRule{
608+
{
609+
APIGroups: []string{authorization.GroupName},
610+
Verbs: sets.NewString("create"),
611+
Resources: sets.NewString("subjectaccessreviews"),
612+
},
613+
{
614+
APIGroups: []string{templateapi.GroupName},
615+
Verbs: sets.NewString("get", "create", "update", "delete"),
616+
Resources: sets.NewString("brokertemplateinstances"),
617+
},
618+
{
619+
APIGroups: []string{templateapi.GroupName},
620+
// "assign" is required for the API server to accept creation of
621+
// TemplateInstance objects with the requester username set to an
622+
// identity which is not the API caller.
623+
Verbs: sets.NewString("get", "create", "delete", "assign"),
624+
Resources: sets.NewString("templateinstances"),
625+
},
626+
{
627+
APIGroups: []string{kapi.GroupName},
628+
Verbs: sets.NewString("get", "list", "create", "delete"),
629+
Resources: sets.NewString("secrets"),
630+
},
631+
{
632+
APIGroups: []string{kapi.GroupName},
633+
Verbs: sets.NewString("list"),
634+
Resources: sets.NewString("services"),
635+
},
636+
},
637+
},
638+
)
639+
if err != nil {
640+
panic(err)
641+
}
591642
}

pkg/cmd/server/origin/controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,8 @@ func (c *MasterConfig) NewOpenshiftControllerInitializers() (map[string]controll
3838
deploymentTrigger := controller.DeploymentTriggerControllerConfig{Codec: codec}
3939
ret["deploymenttrigger"] = deploymentTrigger.RunController
4040

41+
templateInstance := controller.TemplateInstanceControllerConfig{}
42+
ret["templateinstance"] = templateInstance.RunController
43+
4144
return ret, nil
4245
}

pkg/cmd/server/origin/controller/apps.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
deployercontroller "github.com/openshift/origin/pkg/deploy/controller/deployer"
99
deployconfigcontroller "github.com/openshift/origin/pkg/deploy/controller/deploymentconfig"
1010
triggercontroller "github.com/openshift/origin/pkg/deploy/controller/generictrigger"
11+
templatecontroller "github.com/openshift/origin/pkg/template/controller"
1112
)
1213

1314
type DeployerControllerConfig struct {
@@ -25,6 +26,9 @@ type DeploymentTriggerControllerConfig struct {
2526
Codec runtime.Codec
2627
}
2728

29+
type TemplateInstanceControllerConfig struct {
30+
}
31+
2832
func (c *DeployerControllerConfig) RunController(ctx ControllerContext) (bool, error) {
2933
internalDeployerKubeClient, err := ctx.ClientBuilder.KubeInternalClient(bootstrappolicy.InfraDeployerControllerServiceAccountName)
3034
if err != nil {
@@ -87,3 +91,31 @@ func (c *DeploymentTriggerControllerConfig) RunController(ctx ControllerContext)
8791

8892
return true, nil
8993
}
94+
95+
func (c *TemplateInstanceControllerConfig) RunController(ctx ControllerContext) (bool, error) {
96+
saName := bootstrappolicy.InfraTemplateInstanceControllerServiceAccountName
97+
98+
internalKubeClient, err := ctx.ClientBuilder.KubeInternalClient(saName)
99+
if err != nil {
100+
return true, err
101+
}
102+
103+
deprecatedOcClient, err := ctx.ClientBuilder.DeprecatedOpenshiftClient(saName)
104+
if err != nil {
105+
return true, err
106+
}
107+
108+
templateClient, err := ctx.ClientBuilder.OpenshiftTemplateClient(saName)
109+
if err != nil {
110+
return true, err
111+
}
112+
113+
go templatecontroller.NewTemplateInstanceController(
114+
deprecatedOcClient,
115+
internalKubeClient,
116+
templateClient.Template(),
117+
ctx.TemplateInformers.Template().InternalVersion().TemplateInstances(),
118+
).Run(5, ctx.Stop)
119+
120+
return true, nil
121+
}

pkg/cmd/server/origin/controller/interfaces.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99

1010
osclient "github.com/openshift/origin/pkg/client"
1111
"github.com/openshift/origin/pkg/controller/shared"
12+
templateinformer "github.com/openshift/origin/pkg/template/generated/informers/internalversion"
13+
templateclient "github.com/openshift/origin/pkg/template/generated/internalclientset"
1214
)
1315

1416
type ControllerContext struct {
@@ -17,6 +19,8 @@ type ControllerContext struct {
1719
// ClientBuilder will provide a client for this controller to use
1820
ClientBuilder ControllerClientBuilder
1921

22+
TemplateInformers templateinformer.SharedInformerFactory
23+
2024
DeprecatedOpenshiftInformers shared.InformerFactory
2125

2226
// Stop is the stop channel
@@ -34,6 +38,7 @@ type ControllerClientBuilder interface {
3438
KubeInternalClientOrDie(name string) kclientsetinternal.Interface
3539
DeprecatedOpenshiftClient(name string) (osclient.Interface, error)
3640
DeprecatedOpenshiftClientOrDie(name string) osclient.Interface
41+
OpenshiftTemplateClient(name string) (templateclient.Interface, error)
3742
}
3843

3944
// InitFunc is used to launch a particular controller. It may run additional "should I activate checks".
@@ -76,3 +81,11 @@ func (b OpenshiftControllerClientBuilder) DeprecatedOpenshiftClientOrDie(name st
7681
}
7782
return client
7883
}
84+
85+
func (b OpenshiftControllerClientBuilder) OpenshiftTemplateClient(name string) (templateclient.Interface, error) {
86+
clientConfig, err := b.Config(name)
87+
if err != nil {
88+
return nil, err
89+
}
90+
return templateclient.NewForConfig(clientConfig)
91+
}

pkg/cmd/server/origin/master.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,9 @@ func (c *MasterConfig) InstallProtectedAPI(server *apiserver.GenericAPIServer) (
512512
templateapi.ServiceBrokerRoot,
513513
templateservicebroker.NewBroker(
514514
c.PrivilegedLoopbackClientConfig,
515-
c.PrivilegedLoopbackOpenShiftClient,
516-
c.PrivilegedLoopbackKubernetesClientsetInternal.Core(),
517-
c.Informers,
515+
c.PrivilegedLoopbackKubernetesClientsetInternal,
516+
c.Options.PolicyConfig.OpenShiftInfrastructureNamespace,
517+
c.TemplateInformers.Template().InternalVersion().Templates(),
518518
c.Options.TemplateServiceBrokerConfig.TemplateNamespaces,
519519
),
520520
)
@@ -895,12 +895,13 @@ func (c *MasterConfig) GetRestStorage() map[schema.GroupVersion]map[string]rest.
895895
}
896896

897897
if c.Options.TemplateServiceBrokerConfig != nil {
898-
templateInstanceStorage, err := templateinstanceetcd.NewREST(c.RESTOptionsGetter, c.PrivilegedLoopbackOpenShiftClient)
898+
templateInstanceStorage, templateInstanceStatusStorage, err := templateinstanceetcd.NewREST(c.RESTOptionsGetter, c.PrivilegedLoopbackKubernetesClientsetInternal)
899899
checkStorageErr(err)
900900
brokerTemplateInstanceStorage, err := brokertemplateinstanceetcd.NewREST(c.RESTOptionsGetter)
901901
checkStorageErr(err)
902902

903903
storage[templateapiv1.SchemeGroupVersion]["templateinstances"] = templateInstanceStorage
904+
storage[templateapiv1.SchemeGroupVersion]["templateinstances/status"] = templateInstanceStatusStorage
904905
storage[templateapiv1.SchemeGroupVersion]["brokertemplateinstances"] = brokerTemplateInstanceStorage
905906
}
906907

0 commit comments

Comments
 (0)