|
| 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 | + |
| 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 | + |
| 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 |
0 commit comments