Skip to content
This repository was archived by the owner on May 6, 2022. It is now read-only.

Commit 648d0c0

Browse files
committed
Proposal: ns-scoped resources for brokers, services, and plans
1 parent 55505be commit 648d0c0

File tree

1 file changed

+256
-0
lines changed

1 file changed

+256
-0
lines changed

docs/proposals/ns-scoped-catalog.md

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# Proposal: Controlling access to Services and Plans
2+
3+
## Abstract
4+
5+
Proposes changes to service-catalog to facilitate controlling access to certain services and plans.
6+
7+
## Motivation
8+
9+
Not all services and plans should be available to all users. The existing cluster-scoped resources for brokers, services, and plans are not sufficient to implement access control to ensure that users have access only to the service and plans that they should.
10+
11+
Additionally, when developers are creating new services that are exposed by brokers, they want to be able to iterate on those services without exposing them to all users in a cluster.
12+
13+
There are two ingredients to successfully controlling access to services and plans:
14+
15+
- Namespaced versions of these resources are required to control access to services along the boundaries of namespaces
16+
- API surfaces to allow black/whitelisting which services and plans from a broker's catalog have k8s resources created for them
17+
18+
## Use Cases
19+
20+
- As a cluster operator, I want to control access to certain services and plans so that only certain namespaces are allowed to use them
21+
- As a developer, I want to be able to add a broker just to my namespace, so that I can iterate on new service I am developing without exposing services and plans to users of the cluster
22+
23+
### Use Case: Controlling access to services and plans
24+
25+
Certain services or plans are not suitable for consumption by every user of a cluster. For example, a service may have a monetary cost associated with it or grant the user a high degree of privilege. In order to prevent users from gaining access to services and/or plans that they should not be able to use, we must be able to:
26+
27+
1. Keep the services and plans in the cluster-scoped catalog limited to those that anyone can use
28+
2. Allow services and plans that are only for certain users to be used only by the users that should have access to them
29+
30+
For example: a broker may offer a highly-privileged service that ordinary users should not even be aware of, let alone allowed to use. In this case, the cluster administrator should be able to keep that service from appearing in the cluster-scoped catalog of services and plans but also make it available to users with the appropriate level of privilege.
31+
32+
### Use Case: Developing new services
33+
34+
Similar to to highly privileged services, there are a class of users who are service developers, and would be interested in publishing their services via a broker to the rest of the cluster. As part of their development cycle, they would like to work within their own private namespace while iterating on their service.
35+
36+
## Goals and non-goals
37+
38+
There are many related problems in service-catalog that users are interested in solutions for, but we need to keep the scope of this proposal controlled. In that light, let's establish the goals of this proposal:
39+
40+
- Make it possible to keep the cluster-scoped catalog limited to services and plans that everyone should be able to use
41+
- Make it possible to add privileged services and plans into specific namespaces
42+
43+
The following are valid goals but outside the scope of this proposal:
44+
45+
- Make it possible to use a service and plan from namespace X to provision a `ServiceInstance` in namespace Y
46+
- Allow creating a `ServiceBinding` in namespace X to a `ServiceInstance` in namespace Y
47+
- Expose a service and plan in namespace X to the cluster scope
48+
- Expose a service and plan in namespace X to namespace Y
49+
- Create a policy that adds certain services and plans to multiple namespaces
50+
- Creating a virtual resource that allows users to see all services or plans available to them across the cluster and namespace scopes
51+
52+
We should take care to acheive the goals of this proposal without preventing further progress on other issues that are out of scope.
53+
54+
## Analysis
55+
56+
### Why namespaces?
57+
58+
Unfortunately, it is not possible in Kubernetes to create an ACL (access control list) filtering scheme that shows users only the resources in a collection that they are allowed to see. The fundamental gaps here are:
59+
60+
1. Not all authorizers are able to provide a list of subjects with access to a resource
61+
2. An external authorizer may have its state changed at any time out of band to kubernetes, making it impossible to do implement a correct `LIST` or `WATCH` operation from a certain resource version
62+
63+
Since ACL-filtering the cluster-scoped list of services and plans is not a realistic option, we must find another method of controlling read/write access to resources. In Kubernetes, namespaces are the defacto way of performing this type of access control.
64+
65+
Adding namespaced resources for service brokers (`ClusterServiceBroker`), services (`ClusterServiceClass`) and plans (`ClusterServicePlans`) allows us to take advantage of the existing namespace concept to perform access control.
66+
67+
### Filtering services and plans from a broker
68+
69+
Adding namespaced resources for brokers, services and plans is necessary but not sufficient to control access to services and plans. A single broker may offer a mix of services that all users should be able to access and services that should only be usable by some users.
70+
71+
In order to prevent a broker that offers a mix of unprivileged and privileged services to the cluster-scoped catalog, there must be a way to filter the services and plans exposed by a broker. This can be accomplished through the use of white/black lists that control which services and plans in a broker's catalog have service-catalog resources created for them. For example:
72+
73+
- A cluster administrator should be able to prevent privileged services from appearing in cluster-scoped catalog
74+
- A cluster administrator should be able to add certain privileged services to a namespace
75+
76+
## Design
77+
78+
In this proposal we'll focus on adding the namespaced `ServiceBroker`, `ServiceClass`, and `ServicePlan` resources. For details on filtering which services and plans in a broker's catalog have k8s resources created for them, see https://github.com/kubernetes-incubator/service-catalog/pull/1773.
79+
80+
### Namespaced resources
81+
82+
The namespaced resources for brokers, services, and plans should have the same behaviors as their cluster-scoped cousins. To a great degree, we can reuse the same API fields in the namespaced resources, but there are some exceptions:
83+
84+
#### `ServiceBroker` resource
85+
86+
The API for the `ServiceBroker` resource should differ from `ClusterServiceBroker` in exactly one area:
87+
88+
- A user should only be able to specify a secret within the same namespace to hold the auth information
89+
90+
#### `ServiceClass` resource
91+
92+
Differences between `ClusterServiceClass` and `ServiceClass`:
93+
94+
- `ServiceClass.Spec` should have `ServiceBrokerName` instead of `ClusterServiceBrokerName`
95+
96+
#### `ServicePlan` resource
97+
98+
Differences between `ClusterServicePlan` and `ServicePlan`
99+
100+
- `ServicePlan.Spec` should have `ServiceBrokerName` instead of `ClusterServiceBrokerName`
101+
- `ServicePlan.Spec` should have `ServiceClassRef` instead of `ClusterServiceClassRef`
102+
103+
### Changes to `ServiceInstance`
104+
105+
The `ServiceInstance` resource should be changed to allow users to unambiguously specify a `ServiceClass` and `ServicePlan` instead of the cluster-level resources.
106+
107+
- Add fields to `PlanReference` to represent the external and k8s names of `ServiceClass` and `ServicePlan` (as opposed to the cluster-scoped versions)
108+
- Add reference fields to `ServiceInstanceSpec` that represent the references to the namespaced resources
109+
110+
## Implementation plan
111+
112+
The implementation of this proposal is too large for a single PR, so we'll break it into stages:
113+
114+
### Extracting shared fields from existing resources
115+
116+
To extract the shared fields, we will:
117+
118+
- Extract the identified shared fields onto embedable types: `SharedServiceBrokerSpec`, `SharedServiceClassSpec`, and `SharedServicePlanSpec`.
119+
- Embed these shared types within their respective cluster scoped specs.
120+
- Minor controller changes to reflect the fact that these fields now belong to an embedded type.
121+
- Required updates to the fuzzer, validations, and defaults where necessary.
122+
123+
This PR will result in no behavioral changes, and should remain entirely transparent to users. It is effectively a no-op.
124+
125+
Relevant API types after this step:
126+
127+
```go
128+
129+
type ClusterServiceBrokerSpec struct {
130+
SharedServiceBrokerSpec `json:",inline"`
131+
132+
AuthInfo *ClusterServiceBrokerAuthInfo `json:"authInfo,omitempty"`
133+
}
134+
135+
type ClusterServiceBrokerStatus struct {
136+
SharedServiceBrokerStatus `json:",inline"`
137+
}
138+
139+
type ClusterServiceClassSpec struct {
140+
SharedServiceClassSpec `json:",inline"`
141+
142+
ClusterServiceBrokerName string `json:"clusterServiceBrokerName"`
143+
}
144+
145+
type ClusterServiceClassStatus struct {
146+
SharedServiceClassStatus `json:",inline"`
147+
}
148+
149+
type ClusterServicePlanSpec struct {
150+
SharedServicePlanSpec `json:",inline"`
151+
152+
ClusterServiceBrokerName string `json:"clusterServiceBrokerName"`
153+
154+
ClusterServiceClassRef ClusterObjectReference `json:"clusterServiceClassRef"`
155+
}
156+
157+
type ClusterServicePlanStatus struct {
158+
SharedServicePlanStatus `json:",inline"`
159+
}
160+
```
161+
162+
### Add API surface for ns-scoped resources
163+
164+
After shared fields are extracted, we will add:
165+
166+
- API resources for the new namespace-scoped resources
167+
- Associated validations / fuzzers / client changes / etc
168+
- A feature gate that controls whether the ns-scoped resources are enabled
169+
170+
The feature gate is necessary to ensure that users do not see resources that aren't fully functional and will be removed after the proposal is completely implemented.
171+
172+
The new resources will look as follows:
173+
174+
```go
175+
type ServiceBrokerSpec struct {
176+
SharedServiceBrokerSpec `json:",inline"`
177+
178+
AuthInfo *ServiceBrokerAuthInfo `json:"authInfo,omitempty"`
179+
}
180+
181+
type ServiceBrokerStatus struct {
182+
SharedServiceBrokerStatus `json:",inline"`
183+
}
184+
185+
type ServiceClassSpec struct {
186+
SharedServiceClassSpec `json:",inline"`
187+
188+
ServiceBrokerName string `json:"serviceBrokerName"`
189+
}
190+
191+
type ServiceClassStatus struct {
192+
SharedServiceClassStatus `json:",inline"`
193+
}
194+
195+
type ServicePlanSpec struct {
196+
SharedServicePlanSpec `json:",inline"`
197+
198+
ServiceBrokerName `json:"serviceBrokerName"`
199+
200+
ServiceClassRef LocalObjectReference `json:"serviceClassRef"`
201+
}
202+
203+
type ServicePlanStatus struct {
204+
SharedServicePlanStatus `json:",inline"`
205+
}
206+
```
207+
208+
After this step, we will have the namespaced resources for brokers, services, and plans, but they will not be functional yet.
209+
210+
### Add control loops for ns-scoped resources
211+
212+
Next, we will add control loops for the new namespaced resources for brokers, services, and plans.
213+
214+
We'll also add associated tests (similar to broker integration tests that already exist).
215+
216+
After this step, users will be able to add a broker to a namespace and see the namespaced services and plans populated, but they won't be able to provision an instance of a namespaced service/plan yet.
217+
218+
### Make it possible to provision instances of ns-scoped services and plans
219+
220+
Next, we will make it possible to provision an instance of a namespaced service and plan. This involves:
221+
222+
- Adding new fields to `ServiceInstanceSpec` for users to indicate which ns-scoped services they want
223+
- Adding new fields to `ServiceInstanceSpec` for references to ns-scoped resources
224+
- Associated validations / fuzzers for those fields
225+
- Modifying the reference subresource to set the new reference fields appropriately
226+
- Modifying the controller to resolve the new specification fields and set reference fields
227+
228+
Relevant API resources at this step:
229+
230+
```go
231+
type PlanReference struct {
232+
// existing fields omitted
233+
234+
ServiceClassExternalName string `json:"serviceClassExternalName"`
235+
ServiceClassName string `json:"serviceClassName"`
236+
ServicePlanExternalName string `json:"servicePlanExternalName"`
237+
ServicePlanName string `json:"servicePlanName"`
238+
}
239+
240+
type ServiceInstanceSpec struct {
241+
// existing fields omitted
242+
243+
ServiceClassRef *LocalObjectReference `json:"serviceClassRef,omitempty"`
244+
ServicePlanRef *LocalObjectReference `json:"servicePlanRef,omitempty"`
245+
}
246+
```
247+
248+
After this step, users will be able to provision (but not bind to) ns-scoped services and plans.
249+
250+
### Make it possible to bind to instances of ns-scoped services and plans
251+
252+
Next, we will make the required changes to the binding controller loop to make it possible to create bindings against service instances that are associated with the ns-scoped variants of serviceclasses and plans.
253+
254+
### Remove feature flag
255+
256+
Finally, the feature flag will be removed to graduate this feature as enabled by default.

0 commit comments

Comments
 (0)