|
13 | 13 | one associated with a google or github account. Note, the ID used for login
|
14 | 14 | and the providers available can all be configured.
|
15 | 15 |
|
16 |
| -```bash |
17 |
| -kuberift users grant <cluster-role> <email-address> |
18 |
| -``` |
| 16 | + ```bash |
| 17 | + kuberift users grant <cluster-role> <email-address> |
| 18 | + ``` |
19 | 19 |
|
20 | 20 | 1. Start the server.
|
21 | 21 |
|
22 |
| -```bash |
23 |
| -kuberift --serve |
24 |
| -``` |
| 22 | + ```bash |
| 23 | + kuberift --serve |
| 24 | + ``` |
25 | 25 |
|
26 | 26 | 1. SSH into your cluster!
|
27 | 27 |
|
28 |
| -```bash |
29 |
| -ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 2222 me@localhost |
30 |
| -``` |
| 28 | + ```bash |
| 29 | + ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 2222 me@localhost |
| 30 | + ``` |
31 | 31 |
|
32 | 32 | From this point, here's a few suggestions for things to check out:
|
33 | 33 |
|
@@ -102,85 +102,6 @@ look at the configuration for `kuberift serve` for the required values.
|
102 | 102 | https://auth0.com/docs/get-started/authentication-and-authorization-flow/device-authorization-flow/call-your-api-using-the-device-authorization-flow#prerequisites
|
103 | 103 | [device-code]: https://www.oauth.com/oauth2-servers/device-flow/
|
104 | 104 |
|
105 |
| -## Metrics |
106 |
| - |
107 |
| -- bytes_received_total - Total number of bytes received. This should be keyboard |
108 |
| - input. |
109 |
| -- channel_bytes_sent_total - Total number of bytes sent via a channel by IO type |
110 |
| - (blocking, non-blocking). This is what the UI and raw modes use to send data |
111 |
| - to the client. It will be different that the amount of bytes `russh` itself. |
112 |
| -- ssh_clients_total - Number of incoming connections. |
113 |
| -- ssh_session_errors_total - Number of non-IO related unhandled errors at the |
114 |
| - session level. |
115 |
| -- session_total - Number of sessions created. |
116 |
| -- active_sessions - Number of currently active sessions. |
117 |
| -- session_duration_minutes - Duration of a session in minutes. |
118 |
| -- unexpected_state_total - Number of times an unexpected state was encountered. |
119 |
| - This should only be incremented if there's a bug. |
120 |
| -- auth_attempts_total - Number of authentication attempts by method (publickey, |
121 |
| - interactive). This can seem inflated because `publickey` will always be |
122 |
| - attempted first and `interactive` will happen at least twice for every |
123 |
| - success. |
124 |
| -- auth_results_total - Number of auth responses returned by method and result |
125 |
| - (accept, partial, reject). Note that this can seem inflated because |
126 |
| - `publickey` is always attempted first and provides a rejection before moving |
127 |
| - onto other methods. |
128 |
| -- auth_succeeded_total - Number of fully authn and authz'd users. After this, |
129 |
| - users can request a PTY. |
130 |
| -- code_generated_total - Number of codes generated for users. This is the first |
131 |
| - half of the `interactive` mode. |
132 |
| -- code_checked_total - Number of codes that have been checked by result (valid, |
133 |
| - invalid). This is the second half of the `interactive` mode and it is possible |
134 |
| - that users retry after getting `invalid` because of something on the openid |
135 |
| - provider side. |
136 |
| -- window_resize_total - Number of times the window has been asked to resize. |
137 |
| -- container_exec_duration_minutes - Number of minutes a raw terminal was running |
138 |
| - exec'd into a pod. |
139 |
| -- table_filter_total - Number of times a table was filtered. |
140 |
| -- widget_views_total - Number of times a widget was created by resource |
141 |
| - (container, pod) and type (cmd, log, yaml, ...). |
142 |
| - |
143 |
| -## Identity (Authentication) |
144 |
| - |
145 |
| -Access is managed via k8s' RBAC system. This is managed with `User` and `Group` |
146 |
| -subjects in role bindings. Kuberift impersonates a user with optional groups. |
147 |
| -Authorization is then managed by k8s itself. |
148 |
| - |
149 |
| -There are two ways for an incoming SSH session to get a user identity: |
150 |
| - |
151 |
| -- OpenID - If the user does not have an authorized public key, the SSH session |
152 |
| - prompts with an open id flow. When that flow is successful, the returned token |
153 |
| - is mapped to a k8s identity. By default, this is the `email` claim in the |
154 |
| - identity token. If you would like to map different claims and/or add groups, |
155 |
| - take a look at the server configuration. |
156 |
| -- Public Key - By default, once a user has been authenticated with open id, they |
157 |
| - will have a public key. This will contain the user and group information |
158 |
| - extracted from the identity token. If you would like to skip OpenID entirely, |
159 |
| - you can create `Key` resources, the `kuberift users key` can be used to do |
160 |
| - this as an alternative to `kubectl`. |
161 |
| - |
162 |
| -To validate that a user has access, you can use the `kuberift users check` |
163 |
| -command. This is a great way to debug why users are not being allowed to |
164 |
| -connect. |
165 |
| - |
166 |
| -```bash |
167 |
| -kuberift users check foo@bar.com |
168 |
| -``` |
169 |
| - |
170 |
| -## Authorization |
171 |
| - |
172 |
| -To be authorized, either the name or groups for a user need to have role |
173 |
| -bindings added to the cluster. The `kuberift users grant` command is one way to |
174 |
| -go about this, but it is purposely naive. To do something more flexible, you can |
175 |
| -check out `kubectl`: |
176 |
| - |
177 |
| -```bash |
178 |
| -kubectl create clusterrolebinding foo-bar-com --clusterrole=<my-role> --user=foo@bar.com |
179 |
| -``` |
180 |
| - |
181 |
| -Note that you can use `RoleBinding` instead, but that comes with caveats. See |
182 |
| -the design decisions section for an explanation of what's happening there. |
183 |
| - |
184 | 105 | ## Server RBAC
|
185 | 106 |
|
186 | 107 | The kuberift server needs to be able to:
|
@@ -225,10 +146,89 @@ rules:
|
225 | 146 | ---
|
226 | 147 | ```
|
227 | 148 |
|
228 |
| -## Minimum Permissions |
| 149 | +## Identity (Authentication) |
| 150 | + |
| 151 | +Access is managed via k8s' RBAC system. This is managed with `User` and `Group` |
| 152 | +subjects in role bindings. Kuberift impersonates a user with optional groups. |
| 153 | +Authorization is then managed by k8s itself. |
| 154 | + |
| 155 | +There are two ways for an incoming SSH session to get a user identity: |
| 156 | + |
| 157 | +- OpenID - If the user does not have an authorized public key, the SSH session |
| 158 | + prompts with an open id flow. When that flow is successful, the returned token |
| 159 | + is mapped to a k8s identity. By default, this is the `email` claim in the |
| 160 | + identity token. If you would like to map different claims and/or add groups, |
| 161 | + take a look at the server configuration. |
| 162 | +- Public Key - By default, once a user has been authenticated with open id, they |
| 163 | + will have a public key. This will contain the user and group information |
| 164 | + extracted from the identity token. If you would like to skip OpenID entirely, |
| 165 | + you can create `Key` resources, the `kuberift users key` can be used to do |
| 166 | + this as an alternative to `kubectl`. |
| 167 | + |
| 168 | +To validate that a user has access, you can use the `kuberift users check` |
| 169 | +command. This is a great way to debug why users are not being allowed to |
| 170 | +connect. |
| 171 | + |
| 172 | +```bash |
| 173 | +kuberift users check foo@bar.com |
| 174 | +``` |
| 175 | + |
| 176 | +## Authorization |
| 177 | + |
| 178 | +To be authorized, either the name or groups for a user need to have role |
| 179 | +bindings added to the cluster. The `kuberift users grant` command is one way to |
| 180 | +go about this, but it is purposely naive. To do something more flexible, you can |
| 181 | +check out `kubectl`: |
| 182 | + |
| 183 | +```bash |
| 184 | +kubectl create clusterrolebinding foo-bar-com --clusterrole=<my-role> --user=foo@bar.com |
| 185 | +``` |
| 186 | + |
| 187 | +Note that you can use `RoleBinding` instead, but that comes with caveats. See |
| 188 | +the design decisions section for an explanation of what's happening there. |
| 189 | + |
| 190 | +### Minimum Permissions |
229 | 191 |
|
230 | 192 | - List pods at the cluster level.
|
231 | 193 |
|
| 194 | +## Metrics |
| 195 | + |
| 196 | +- bytes_received_total - Total number of bytes received. This should be keyboard |
| 197 | + input. |
| 198 | +- channel_bytes_sent_total - Total number of bytes sent via a channel by IO type |
| 199 | + (blocking, non-blocking). This is what the UI and raw modes use to send data |
| 200 | + to the client. It will be different that the amount of bytes `russh` itself. |
| 201 | +- ssh_clients_total - Number of incoming connections. |
| 202 | +- ssh_session_errors_total - Number of non-IO related unhandled errors at the |
| 203 | + session level. |
| 204 | +- session_total - Number of sessions created. |
| 205 | +- active_sessions - Number of currently active sessions. |
| 206 | +- session_duration_minutes - Duration of a session in minutes. |
| 207 | +- unexpected_state_total - Number of times an unexpected state was encountered. |
| 208 | + This should only be incremented if there's a bug. |
| 209 | +- auth_attempts_total - Number of authentication attempts by method (publickey, |
| 210 | + interactive). This can seem inflated because `publickey` will always be |
| 211 | + attempted first and `interactive` will happen at least twice for every |
| 212 | + success. |
| 213 | +- auth_results_total - Number of auth responses returned by method and result |
| 214 | + (accept, partial, reject). Note that this can seem inflated because |
| 215 | + `publickey` is always attempted first and provides a rejection before moving |
| 216 | + onto other methods. |
| 217 | +- auth_succeeded_total - Number of fully authn and authz'd users. After this, |
| 218 | + users can request a PTY. |
| 219 | +- code_generated_total - Number of codes generated for users. This is the first |
| 220 | + half of the `interactive` mode. |
| 221 | +- code_checked_total - Number of codes that have been checked by result (valid, |
| 222 | + invalid). This is the second half of the `interactive` mode and it is possible |
| 223 | + that users retry after getting `invalid` because of something on the openid |
| 224 | + provider side. |
| 225 | +- window_resize_total - Number of times the window has been asked to resize. |
| 226 | +- container_exec_duration_minutes - Number of minutes a raw terminal was running |
| 227 | + exec'd into a pod. |
| 228 | +- table_filter_total - Number of times a table was filtered. |
| 229 | +- widget_views_total - Number of times a widget was created by resource |
| 230 | + (container, pod) and type (cmd, log, yaml, ...). |
| 231 | + |
232 | 232 | ## Design Decisions
|
233 | 233 |
|
234 | 234 | - Instead of having a separate `User` CRD to track the user, we rely on k8s'
|
@@ -258,19 +258,15 @@ rules:
|
258 | 258 | this. The closest to the OpenID spec would be via adding extra scopes that add
|
259 | 259 | the data required to the token and then map back to a group. Imagine:
|
260 | 260 |
|
261 |
| -```yaml |
262 |
| -user: email |
263 |
| -group: https://myapp.example.com/group |
264 |
| -``` |
| 261 | + ```yaml |
| 262 | + user: email |
| 263 | + group: https://myapp.example.com/group |
| 264 | + ``` |
265 | 265 |
|
266 |
| -The downside to using this kind of configuration is that it'll need to be |
267 |
| -handled in the provider backend and it is unclear how easy that'll be. It is |
268 |
| -possible in auth0, so I'll go down this route for now. |
| 266 | + The downside to using this kind of configuration is that it'll need to be |
| 267 | + handled in the provider backend and it is unclear how easy that'll be. It is |
| 268 | + possible in auth0, so I'll go down this route for now. |
269 | 269 |
|
270 | 270 | - Is there a way to do FPS on a per-session basis with prometheus? Naively the
|
271 | 271 | way to do it would be to have a per-session label value, but that would be
|
272 | 272 | crazy for cardinality.
|
273 |
| -
|
274 |
| -``` |
275 |
| - |
276 |
| -``` |
0 commit comments