Skip to content

Commit c6114df

Browse files
committed
docs/proposal: submit poll based binding
1 parent 0644b16 commit c6114df

3 files changed

Lines changed: 149 additions & 0 deletions

File tree

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
type: proposal
3+
title: Global / Federated Rules API
4+
status: in-progress
5+
owner: s-urbaniak
6+
---
7+
8+
* **Owners:**
9+
* @s-urbaniak
10+
11+
* **Related Tickets:**
12+
* N/A
13+
14+
## Summary
15+
16+
kube-bind offers a user-friendly approach of being able to bind API resources provided by an external party using a simple URL. This URL can be invoked directly via the terminal and the rest of the binding process is finalized in a user web browser session.
17+
18+
At the end a local callback ensures that the necessary metadata of the binding process is passed back to the kubectl `bind` process.
19+
20+
While being user-friendly the current approach has a couple of drawbacks. An alternative method is described which adds a new "polling" based approach vs. the current "callback" based approach.
21+
22+
## Why
23+
24+
kube-bind allows to bind APIs offered by providers using a URL passed to the `bind` subcommand.
25+
As part of the binding process the following steps are executed:
26+
27+
1. The kubectl `bind` plugin retrieves provider metadata
28+
which includes information about supported authentication methods at the provider.
29+
Currently, OAuth 2 code grant flow is supported.
30+
2. The kubectl `bind` renders an authentication URL on the terminal,
31+
augmented with additional session data.
32+
3. The user executes the rendered URL link
33+
and finalizes authentication and API selection in his local browser.
34+
35+
kubectl `bind` plugin blocks until authentication and API selection is finalized.
36+
Currently, this is accomplished using a localhost web server listening on an ephemeral local port on the user machine.
37+
38+
After the end of the above process the kube-bind backend invokes an HTTP 302 localhost redirect in the user browser session. The callback URL includes a serialized `kubebindv1alpha1.BindingResponse` JSON object. This object is passed as a base64 encoded `response` parameter which is added to the callback localhost URL as a query parameter.
39+
40+
The following figure illustrates the current process:
41+
42+
![](localhost-callback.png)
43+
Link: https://whimsical.com/kube-bind-auth-flow-FYCNPvj5m27pKUDVYxVRGy
44+
45+
The current solution has a couple of drawbacks:
46+
47+
1. The kubectl `bind` plugin starts localhost a web server running on the user machine. This makes it currently impossible to use kubectl `bind` on a remote machine i.e. via an SSH session.
48+
49+
2. The serialized encoded length of the `kubebindv1alpha1.BindingResponse` is currently passed as a URL parameter which should not exceed ~2000 characters in most web browser implementations. Worse, this upper bound is not standardized. Finally, passing large URL parameters is not recommended.
50+
51+
The current method will be called as "callback based" approach in the remainder of this proposal.
52+
53+
## Goals
54+
55+
1. *MUST* enable the possibility to use kubectl `bind` on a remote machine i.e. via an SSH session.
56+
2. *MUST* remove the necessity to start a localhost web server on the user machine.
57+
3. *MUST* remove the limitation of encoding the binding response object via a URL query parameter.
58+
4. *MUST* retain user-friendliness of invoking a single URL to bind external APIs.
59+
60+
## How
61+
62+
Next to the above describe "callback based" approach kubectl `bind` additionally supports a "polling" based approach.
63+
64+
Instead of having a localhost web server blocking until a callback http request is executed by the user web browser session, the kubectl `bind` process regularly polls the kube-bind backend whether the authentication and API resource selection process is finalized.
65+
66+
As a result, the kubectl `bind` process downloads the `kubebindv1alpha1.BindingResponse` JSON object directly from the polled URL.
67+
68+
Here, the following steps are executed:
69+
70+
1. The kubectl `bind` plugin retrieves provider metadata
71+
which includes information about supported authentication methods at the provider.
72+
73+
Here, a new authentication polling based variant of the OAuth2 code grant called `OAuth2CodeGrantPoll` is introduced:
74+
75+
```yaml
76+
type BindingProvider struct {
77+
metav1.TypeMeta `json:",inline"`
78+
79+
AuthenticationMethods []AuthenticationMethod `json:"authenticationMethods,omitempty"`
80+
}
81+
82+
type AuthenticationMethod struct {
83+
// method is the name of the authentication method. The follow methods are supported:
84+
//
85+
// - "OAuth2CodeGrant"
86+
// - "OAuth2CodeGrantPoll"
87+
//
88+
Method string `json:"method,omitempty"`
89+
90+
// OAuth2CodeGrant is the configuration for the OAuth2 code grant flow.
91+
OAuth2CodeGrant *OAuth2CodeGrant `json:"oauth2CodeGrant,omitempty"`
92+
93+
// OAuth2CodeGrant is the configuration for the OAuth2 code grant flow
94+
// using a poll based approach.
95+
OAuth2CodeGrantPoll *OAuth2CodeGrantPoll `json:"oauth2CodeGrantPoll,omitempty"`
96+
}
97+
98+
type OAuth2CodeGrantPoll struct {
99+
// authenticatedURL is the service provider url that the service consumer will use to authenticate against
100+
// the service provider in case of using OIDC mode made, e.g: www.mangodb.com/kubernetes/authorize.
101+
//
102+
// +required
103+
// +kubebuilder:validation:Required
104+
// +kubebuilder:validation:MinLength=1
105+
AuthenticatedURL string `json:"authenticatedURL"`
106+
107+
// pollURL is the service provider url that is used to be poll regularly, i.e. "www.mangodb.com/bound".
108+
// The backend returns a HTTP 403 while the process is ongoing
109+
// and a HTTP 200 status code once the authentication and API resource selection is finalized.
110+
// The http response body includes the `kubebindv1alpha1.BindingResponse` object.
111+
//
112+
// +required
113+
// +kubebuilder:validation:Required
114+
// +kubebuilder:validation:MinLength=1
115+
PollURL string `json:"pollURL"`
116+
117+
// pollInterval is the expected polling interval in Go's `time.Duration` format.
118+
// If exceeded, the kube-bind backend may return a 429 Too Many Requests http status code.
119+
//
120+
// +required
121+
// +kubebuilder:validation:Required
122+
// +kubebuilder:validation:MinLength=1
123+
PollInterval string `json:"pollInterval"`
124+
}
125+
```
126+
127+
2. The kubectl `bind` renders an authentication URL on the terminal,
128+
augmented with additional session data.
129+
130+
3. The user executes the rendered URL link
131+
and finalizes authentication and API selection in his local browser.
132+
133+
4. kubectl `bind` regularly polls at every `pollInterval`.
134+
While the user process is ongoing in the user browser session
135+
the kube-bind backend returns an HTTP 403 status code.
136+
Once the user process is finalized the kube-bind backend returns an HTTP 200 status code.
137+
The response body includes the `kubebindv1alpha1.BindingResponse` object.
138+
139+
kubectl `bind` plugin blocks until authentication and API selection is finalized.
140+
141+
The following figure illustrates the poll based approach:
142+
143+
![](poll-based.png)
144+
Link: https://whimsical.com/kube-bind-auth-flow-FYCNPvj5m27pKUDVYxVRGy
145+
146+
TODO(sur): finalize describing the kube-bind backend, especially how session state is maintained using group-cache and consistent hashring.
147+
TODO(sur): describe trusted client concept using HMAC
148+
149+
# Alternatives
392 KB
Loading

docs/proposals/poll-based.png

520 KB
Loading

0 commit comments

Comments
 (0)