Skip to content

Commit

Permalink
Merge pull request #1502 from yuvipanda/docsy
Browse files Browse the repository at this point in the history
Setup ability to provide authenticated ingresses to arbitrary web apps
  • Loading branch information
yuvipanda authored Jul 11, 2022
2 parents 349fbf0 + 3a68b4a commit 958f140
Show file tree
Hide file tree
Showing 28 changed files with 694 additions and 186 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ repos:
hooks:
- id: sops-encryption
# Add files here if they contain the word 'secret' but should not be encrypted
exclude: secrets\.md|helm-charts/support/templates/prometheus-ingres-auth/secret\.yaml
exclude: secrets\.md|helm-charts/support/templates/prometheus-ingres-auth/secret\.yaml|helm-charts/basehub/templates/dex/secret\.yaml|helm-charts/basehub/templates/static/secret\.yaml
6 changes: 1 addition & 5 deletions config/clusters/2i2c/cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@ hubs:
domain: staging.2i2c.cloud
helm_chart: basehub
auth0:
# connection update? Also ensure the basehub Helm chart is provided a
# matching value for jupyterhub.custom.2i2c.add_staff_user_ids_of_type!
connection: google-oauth2
helm_chart_values_files:
# The order in which you list files here is the order the will be passed
# to the helm upgrade command in, and that has meaning. Please check
# that you intend for these files to be applied in this order.
- staging.values.yaml
- enc-staging.secret.values.yaml
- name: dask-staging
display_name: "2i2c dask staging"
domain: dask-staging.2i2c.cloud
Expand Down
18 changes: 12 additions & 6 deletions config/clusters/2i2c/enc-staging.secret.values.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
staticWebsite:
githubAuth:
githubApp:
id: ENC[AES256_GCM,data:EDJXakop,iv:BPu3qh9zpMVJWVNxPIfScoaeA+avSsacqxA6adriU98=,tag:wHxbuCOLrjvyu8/m0bj3rg==,type:int]
privateKey: ENC[AES256_GCM,data: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,iv:iu/nD/1zYDo9OY4q+j0sd+E5ODjLHZ3Otbkd0qte8WM=,tag:wD9S4cOGUeCVZIh9mRrI/w==,type:str]
jupyterhub:
hub:
config:
Expand All @@ -7,13 +12,14 @@ jupyterhub:
sops:
kms: []
gcp_kms:
- resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs
created_at: '2022-03-21T10:38:36Z'
enc: CiQA4OM7eJn+A9b0ulwu64MnqKfDM1EwtoKzj7Utg4iXOccLCroSSQDm5XgWCwOR2/FDqBIOrVVltPV7nASpq8h+fiHw5dYTSaPUyAMYwQ62iytA2kwTGQcOMmtxZVhn4dpGt2b0VlEvdiHP02Cgzvo=
- resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs
created_at: "2022-03-21T10:38:36Z"
enc: CiQA4OM7eJn+A9b0ulwu64MnqKfDM1EwtoKzj7Utg4iXOccLCroSSQDm5XgWCwOR2/FDqBIOrVVltPV7nASpq8h+fiHw5dYTSaPUyAMYwQ62iytA2kwTGQcOMmtxZVhn4dpGt2b0VlEvdiHP02Cgzvo=
azure_kv: []
hc_vault: []
lastmodified: '2022-03-21T10:38:36Z'
mac: ENC[AES256_GCM,data:D50ijsF6YmlX/El96nrIgxEcEmfbJabVvKIO33zi8PfjqkQZj7L9XdGMz9FzNRvtSu2+PwhZRr+98pqWb4N2SvuVjqPfskJwigVVQifNxOtI2P3V2LvnA/rnYvvTkpfzrcwBJPHsUL8VCAeY8OjxdEpamqFsrlyFG4z2HQ0dAQg=,iv:uDkxaW/3dZZTer1iuqhfIHtZ8vvOY7TCKfFnaI2pcZM=,tag:XjF32PtqZifGwW0LsKa/8Q==,type:str]
age: []
lastmodified: "2022-07-09T21:14:35Z"
mac: ENC[AES256_GCM,data:xfxx30hp48xu13udRZUkEBX0C4RirV6sO6jqDICdfQkvQI/EtvUWF97GCFWgfAlnOI/W26BSftpg6QW9IwyzUO55PfJy/L4TQ03Ee+thu51tXjAywHfswWvE/ovA9fKQ4fU2QcNHb72Q53qUsx912CR7sXOvQajRekMPXZSJU10=,iv:f195Wlf+Yjods46WKt40Db88J1yGiTZDBWCmQWO3kF0=,tag:PIJAjOIRaLKRVmMFkBxEkQ==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.6.1
version: 3.7.1
29 changes: 25 additions & 4 deletions config/clusters/2i2c/staging.values.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
dex:
enabled: true
hubHostName: staging.2i2c.cloud

staticWebsite:
enabled: true
source:
git:
repo: https://github.com/yuvipanda/test-repo-push
branch: master
ingress:
host: staging.2i2c.cloud
path: /textbook
githubAuth:
enabled: true

jupyterhub:
custom:
docs_service:
enabled: true
repo: https://github.com/jupyterhub/nbgitpuller
branch: gh-pages
2i2c:
add_staff_user_ids_to_admin_users: true
add_staff_user_ids_of_type: "google"
Expand All @@ -23,6 +35,15 @@ jupyterhub:
name: 2i2c
url: https://2i2c.org
hub:
services:
dex:
url: http://dex:5556
oauth_redirect_uri: https://staging.2i2c.cloud/services/dex/callback
oauth_no_confirm: true
display: false
oauth2-proxy:
url: http://dex:9000
display: false
config:
Authenticator:
allowed_users: &staging_users
Expand Down
4 changes: 0 additions & 4 deletions config/clusters/cloudbank/staging.values.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
jupyterhub:
custom:
docs_service:
enabled: true
repo: https://github.com/jupyterhub/nbgitpuller
branch: gh-pages
2i2c:
add_staff_user_ids_to_admin_users: true
add_staff_user_ids_of_type: "google"
Expand Down
34 changes: 0 additions & 34 deletions docs/howto/customize/docs-service.md

This file was deleted.

5 changes: 2 additions & 3 deletions docs/howto/features/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ See the sections below for more details:
cloud-access
gpu
github
../customize/docs-service
../customize/configure-login-page
../operate/override-domain.md
static-sites
login-page
```
File renamed without changes.
162 changes: 162 additions & 0 deletions docs/howto/features/static-sites.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Deploy authenticated static websites along the hub

We can deploy *authenticated* static websites on the same domain as the hub
that is only accessible to users who have access to the hub. The source
for these come from git repositories that should contain rendered HTML,
and will be updated every 5 minutes. They can be under any prefix on the
same domain as the hub (such as `/docs`, `/textbook`, etc).

You can enable this with the following config in the `.values.yaml`
file for your hub.

```yaml

dex:
# Enable authentication
enabled: true
hubHostName: <hostname-of-hub>

staticWebsite:
enabled: true
source:
git:
repo: <url-of-git-repo>
branch: <name-of-git-branch>
ingress:
host: <hostname-of-hub>
path: <absolute-path-where-content-is-available>

jupyterhub:
hub:
services:
dex:
url: http://dex:5556
oauth_redirect_url: https://<hostname-of-hub>/services/dex/callback
oauth_no_confirm: true
display: false
oauth2-proxy:
display: false
url: http://dex:9000

```

```{note}
We manually configure the hub services instead of autogenerating
them in our deploy scripts. This leads to some additional copy-pasting and
duplication, but keeps our config explicit and simple.
```

## Example

Here's a sample that hosts the data8 textbook under `https://staging.2i2c.cloud/textbook`:

```yaml
dex:
enabled: true
hubHostName: staging.2i2c.cloud

staticWebsite:
enabled: true
source:
git:
repo: https://github.com/inferentialthinking/inferentialthinking.github.io
branch: master
ingress:
host: staging.2i2c.cloud
path: /textbook

jupyterhub:
hub:
services:
dex:
url: http://dex:5556
oauth_redirect_uri: https://staging.2i2c.cloud/services/dex/callback
oauth_no_confirm: true
oauth2-proxy:
url: http://dex:9000
```
This clones the [repo]( https://github.com/inferentialthinking/inferentialthinking.github.io),
checks out the `master` branch and keeps it up to date by doing a
`git pull` every 5 minutes. It is made available under `/textbook`,
and requires users be logged-in to the hub before they can access it.

## Using private GitHub repos

We use [git-credentials-helper](https://github.com/yuvipanda/git-credential-helpers)
to support pulling content from private repos.

### Setup GitHub app

`git-credentials-helper` uses a [GitHub App](https://docs.github.com/en/developers/apps)
to pull private repos. So you first need to create a GitHub app for each hub that wants
to pull private repos as static content.

1. Create a [GitHub app in the 2i2c org](https://github.com/organizations/2i2c-org/settings/apps/new).

2. Give it a descriptive name (such as '<hub-name> static site deploy
authenticator') and description, as users will see this when authorizing
access to their private repos.

3. Disable webhooks (uncheck the 'Active' checkbox under 'Webhooks'). All other
textboxes can be left empty.

4. Under 'Repository permissions', select 'Read' for 'Contents'.

5. Under 'Where can this GitHub App be installed?', select 'Any account'. This will
enable users to push to their own user repositories or other organization repositories,
rather than just the 2i2c repos.

6. Create the application with the 'Create GitHub app' button.

7. Copy the numeric 'App id' from the app info page you should be redirected to.

8. Create a new private key for authentication use with the `Generate a private key`
button. This should download a private key file, that you should keep safe.

### Helm values configuration

Now, we can configure our static files server to make use of the GitHub app to authenticate.

1. Enable the gitHub app in the `.values.yaml` file for the hub.

```yaml
staticWebsite:
gitHubAuth:
enabled: true
```

2. Create a sops-encrypted file (usually in the form of
`enc-<hub-name>.secret.values.yaml`) to hold the secret values required to authenticate
the GitHub app.

```yaml
staticWebsite:
githubAuth:
githubApp:
id: <id-of-the-app>
privateKey: |
<contents-of-private-key-file>
```

Make sure this file is also listed under `helm_chart_values_files` for the hub in
the cluster's `cluster.yaml` so it is read during deployment.

### Grant access to the private repo

Finally, someone with admin rights on the private repo to be pulled needs to
grant the github app we just setup access to the private repo. **This is the only
part that hub admins rather than 2i2c engineers need to do**.

1. Go to the 'Public page' of the GitHub app created. This usually is of the
form `https://github.com/apps/<name-of-app>`. You can find this in the information
page of the app after you create it, under 'Public link'

2. Install the app in the organization the private repo is in, and grant it access
*only* to the repo that needs to be pulled.

### Do a deploy

After all the permissions are setup, you should make sure the config under
`staticWebsite.source.git.repo` and `staticWebsite.source.git.repo` are set appropriately, and do a deployment
to pull in the private repo!
2 changes: 1 addition & 1 deletion docs/howto/k8s/node-administration.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Sometimes you might need to delete or to perform maintenance on a node in the cl
* Pods created by [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/) objects, through [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)

Once deleted, these Pods will get re-created and assigned to a different node (because the current node it's cordoned).
The [hub, proxy](https://github.com/2i2c-org/infrastructure/tree/HEAD/helm-charts/basehub/Chart.yaml) and the [docs service](https://github.com/2i2c-org/infrastructure/tree/HEAD/helm-charts/basehub/templates/docs-service-deployment.yaml) are some examples of such pods.
The [hub & proxy](https://github.com/2i2c-org/infrastructure/tree/HEAD/helm-charts/basehub/Chart.yaml) pods are some examples of such pods.
* Pods created by [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) objects.
These run on every node, regardless of their `cordon` status. So, they don't need to be deleted, otherwise, they will be re-created on the same cordoned node.
Expand Down
Binary file removed docs/images/docs-service.png
Binary file not shown.
3 changes: 2 additions & 1 deletion docs/topic/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,5 @@ A single bucket can also be designated as as *scratch bucket*, which will
set a `SCRATCH_BUCKET` (and a deprecated `PANGEO_SCRATCH`) environment variable
of the form `<s3 or gcs>://<bucket-name>/<user-name>`. This can be used by individual
users to store objects temporarily for their own use, although there is nothing
preventing other users from accessing these objects!
preventing other users from accessing these objects!

9 changes: 9 additions & 0 deletions helm-charts/basehub/templates/dex/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Until https://github.com/Masterminds/sprig/issues/282 is fixed
{{- define "randHex" -}}
{{- $result := "" }}
{{- range $i := until . }}
{{- $rand_hex_char := mod (randNumeric 4 | atoi) 16 | printf "%x" }}
{{- $result = print $result $rand_hex_char }}
{{- end }}
{{- $result }}
{{- end }}
Loading

0 comments on commit 958f140

Please sign in to comment.