Skip to content

Commit 08dfd3f

Browse files
committed
chore: add CSP and CORS instructions
1 parent b8b850b commit 08dfd3f

1 file changed

Lines changed: 92 additions & 15 deletions

File tree

docs/docs/20-admins/30-operation/50-remote.md

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ flowchart LR
2525
AmaltheaLocal[Amalthea operator]
2626
Backend
2727
end
28-
28+
2929
Backend --> APIA
3030
APIA --> AmaltheaRemoteA
3131
AmaltheaRemoteA --> SessionA
@@ -119,10 +119,12 @@ This storage class will be used to provide the working directory of the user ses
119119
User session scheduling is based on label and taints to select nodes where to run the pod associated with each user session.
120120
121121
Labels:
122+
122123
- `renku.io/node-purpose: user` User sessions are scheduled only on nodes with this label
123124
- Extra labels to differentiate node pools as required
124125

125126
Taints:
127+
126128
- Taints to differentiate node pools as required
127129

128130
### Namespace
@@ -218,8 +220,7 @@ data:
218220
type: kubernetes.io/service-account-token
219221
```
220222

221-
222-
Now we need to extract these values and format them into a valid `kubeconfig`.
223+
Now we need to extract these values and format them into a valid `kubeconfig`.
223224

224225
```yaml
225226
apiVersion: v1
@@ -285,13 +286,13 @@ CSI-rClone has to run on every node on the remote cluster where sessions may run
285286
Therefore you need to make sure you add the correct tolerations in the values file for the
286287
Helm chart for any taints you may add on nodes intended for user sessions.
287288

288-
```bash
289-
helm install \
290-
--create-namespace \
291-
--namespace csi-rclone \
292-
csi-rclone \
293-
renku/csi-rclone
294-
```
289+
```bash
290+
helm install \
291+
--create-namespace \
292+
--namespace csi-rclone \
293+
csi-rclone \
294+
renku/csi-rclone
295+
```
295296

296297
:::note
297298
The versions of the CSI-rClone between the local and remote clusters must be identical.
@@ -306,12 +307,12 @@ In the previous section we described how to derive the `kubeconfig` for a remote
306307
That kubeconfig now needs to be added into a dedicated secret in the "local" cluster
307308
where the backed services will be able to read it and connect to the remote cluster.
308309

309-
The name of the secret with all the remote cluster `kubeconfig`s can be found in the Helm chart
310-
values file at `.dataService.remoteClustersKubeconfigSecretName`.
310+
The name of the secret with all the remote cluster `kubeconfig`s can be found in the Helm chart
311+
values file at `.dataService.remoteClustersKubeconfigSecretName`.
311312
If you do not have this value specified in your Helm chart (by default it is blank).
312313
Then, you should set the value and upgrade your Helm installation.
313314

314-
Here is an example of the `kubeconfig`s secret, assuming the full Renku deployment
315+
Here is an example of the `kubeconfig`s secret, assuming the full Renku deployment
315316
runs under the `renku` namespace:
316317

317318
```yaml
@@ -351,7 +352,7 @@ for registering the cluster with the API.
351352
The first step is to define the remote cluster parameters, which are stored using the `/cluster` API endpoint.
352353
Below is an example payload, assuming `remote-cluster.yaml` is the key of the secret that contains all `Kubeconfig`s
353354
for the remote clusters. The name of the secret that contains all remote `Kubeconfig`s can be defined at
354-
`.dataService.remoteClustersKubeconfigSecretName` in the Helm chart values.
355+
`.dataService.remoteClustersKubeconfigSecretName` in the Helm chart values.
355356

356357
Adapt the example below as required.
357358

@@ -376,6 +377,82 @@ When using `"session_ingress_use_default_cluster_tls_cert": true`,
376377
_you have to set_ `"session_tls_secret_name": ""` as well, otherwise the API call will fail.
377378
:::
378379
380+
:::note
381+
If creating the resource pool fails with a message like `Could not find cluster with id XXXXXX in the list of clusters`. This means that you either got the cluster ID wrong or you need to restart the `data_service`, `k8s_watcher` and `data_tasks` services after you have added a new kubeconfig to the kubeconfigs secret.
382+
:::
383+
384+
### Security considerations
385+
386+
Renku sessions are embedded in an iframe. And when you run the session on a remote cluster
387+
then the session hostname is different from the website hostname that hosts the iframe.
388+
So to make this work we need to set the `SameSite` property on the session cookie to `none`.
389+
390+
This raises additional security concerns that should be mitigated as follows on the
391+
remote cluster ingress configuration.
392+
393+
:::note
394+
It may acceptable to just always open remote sessions in Renku via a separate tab.
395+
If this is the case then do not set the `SameSite` property to `none` and you do not have
396+
to implement the additional mitigations discussed below.
397+
:::
398+
399+
1. Enable Cross-Origin Resource Sharing (CORS)
400+
401+
```yaml
402+
nginx.ingress.kubernetes.io/enable-cors: "true"
403+
nginx.ingress.kubernetes.io/cors-allow-origin: "https://<remote hostname>"
404+
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
405+
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"
406+
nginx.ingress.kubernetes.io/cors-allow-headers: "$http_access_control_request_headers"
407+
```
408+
409+
:::info
410+
You should add the `--skip-auth-preflight=true` to oauth2proxy in the session.
411+
This can be done via Helm chart values on the amalthea-sessions Helm chart.
412+
:::
413+
414+
2. Specify a Content Security Policy (CSP)
415+
416+
This says what hosts can embed the session in an iframe. If you are using nginx ingress
417+
as the ingress controller, you can set this via the following ingress annotation:
418+
419+
```yaml
420+
nginx.ingress.kubernetes.io/configuration-snippet: |
421+
more_set_headers "Content-Security-Policy: frame-ancestors 'self' <remote hostname>";
422+
```
423+
424+
With all of these ingress headers, the payload to create the cluster configuration via the API
425+
would look something like this:
426+
427+
```yaml
428+
{
429+
"name": "Remote Cluster",
430+
"config_name": "remote-cluster.yaml",
431+
"session_protocol": "https",
432+
"session_host": "sessions.example.org",
433+
"session_port": 443,
434+
"session_path": "/sessions",
435+
"session_ingress_class_name": "renku-user-session-ingress-class",
436+
"session_ingress_annotations":
437+
{
438+
"nginx.ingress.kubernetes.io/enable-cors": "true",
439+
"nginx.ingress.kubernetes.io/cors-allow-origin": "https://<local hostname>",
440+
"nginx.ingress.kubernetes.io/cors-allow-credentials": "true",
441+
"nginx.ingress.kubernetes.io/cors-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
442+
"nginx.ingress.kubernetes.io/cors-allow-headers": '"$http_access_control_request_headers"',
443+
"nginx.ingress.kubernetes.io/configuration-snippet": "more_set_headers \"Content-Security-Policy: frame-ancestors 'self' https://<local hostname>\";\n",
444+
},
445+
"session_storage_class": "renku-user-session-storage-class",
446+
"session_tls_secret_name": "",
447+
"session_ingress_use_default_cluster_tls_cert": true,
448+
}
449+
```
450+
451+
:::warning
452+
Removing or not setting the CORS and CSP headers above can have serious security implications.
453+
If you are using a different controller make sure you set all equivalent annotations.
454+
:::
455+
379456
### Create a resource pool for the remote cluster
380457

381458
Once the cluster connection has been defined, you can use the GET operation to retrieve the cluster connection descriptor, and from there retrieve the associated ULID and create a resource pool which is linked to it.
@@ -442,7 +519,7 @@ https://www.example.org/*
442519

443520
### Restart the backend services
444521

445-
The `renku-data-service`, `renku-k8s-watcher`, and `renku-secrets-storage` pods need to be
522+
The `renku-data-service`, `renku-k8s-watcher`, and `renku-secrets-storage` pods need to be
446523
restarted in order to use the new configuration.
447524

448525
As a check, you may watch the logs as each service will announce all the kubeconfigs being loaded as they restart, or during their first remote connections.

0 commit comments

Comments
 (0)