Skip to content

Commit

Permalink
Add staticSites that can be protected by oauth2-proxy
Browse files Browse the repository at this point in the history
- Uses nginx to serve these, and a 5min git pull to pull a git
  repo. Copied from earlier docs_service code
- Use ingress provider to specify the path under which the
  static site is available, rather than the hub proxy. This is
  simpler and allows us to put them anywehere (like
  staging.2i2c.cloud/textbook rather than
  staging.2i2c.cloud/services/textbook)
- Use nginx-ingress to provide authentication for the static
  server, via https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/
  • Loading branch information
yuvipanda committed Jul 8, 2022
1 parent c9b1876 commit 878288d
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 9 deletions.
8 changes: 8 additions & 0 deletions config/clusters/2i2c/staging.values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ dex:
enabled: true
hubHostName: staging.2i2c.cloud

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

jupyterhub:
custom:
2i2c:
Expand All @@ -27,6 +34,7 @@ jupyterhub:
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
config:
Expand Down
23 changes: 15 additions & 8 deletions helm-charts/basehub/templates/dex/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ metadata:
app: dex
data:
dex.yaml: |
# dex expands env vars in values, but does *not* interpolate
# them. So we can use an env var for OAUTH2_CLIENT_SECRET as
# it is just an expansion, but can not use env vars when constructing
# URLs as there's no interpolation! grr.
issuer: https://{{ .Values.dex.hubHostName }}/services/dex
storage:
type: sqlite3
Expand All @@ -24,17 +20,18 @@ data:
oauth2:
# Don't explicitly require users to grant access via the
# dex interface, for a smoother interface
# dex interface, for a smoother experience
skipApprovalScreen: true
connectors:
- type: oauth
id: hub
name: hub
config:
# Connector config values starting with a "$" will read from the environment.
clientID: service-dex
clientSecret: $HUB_OAUTH2_CLIENT_SECRET
# Env vars are expanded via gomplate, which is present in the
# upstream dex docker image
clientSecret: {{ "{{" }} .Env.HUB_OAUTH2_CLIENT_SECRET {{ "}}" }}
redirectURI: https://{{ .Values.dex.hubHostName }}/services/dex/callback
userIDKey: name
tokenURL: http://proxy-public/hub/api/oauth2/token
Expand All @@ -46,15 +43,25 @@ data:
redirectURIs:
- https://{{ .Values.dex.hubHostName }}/services/oauth2-proxy/oauth2/callback
name: oauth2-proxy
secret: $OAUTH2_PROXY_CLIENT_SECRET
# Env vars are expanded via gomplate, which is present in the
# upstream dex docker image
secret: {{ "{{" }} .Env.OAUTH2_PROXY_CLIENT_SECRET {{ "}}" }}
oauth2-proxy.cfg: |
provider = "oidc"
# This is hardcoded in the dex config
client_id = "oauth2-proxy"
redirect_url = "https://{{ .Values.dex.hubHostName }}/services/oauth2-proxy/oauth2/callback"
oidc_issuer_url = "https://{{ .Values.dex.hubHostName }}/services/dex"
oidc_email_claim = "sub"
# We don't actually use email for anything here, so skip email verification
insecure_oidc_allow_unverified_email = true
email_domains = "*"
# Listen on port 9000
http_address = "http://0.0.0.0:9000"
# Don't require user interaction to log in - treat this more like SSO
skip_provider_button = true
# This is exposed to the internet as a JupyterHub service,
# so it is only available prefixed with this URL
reverse_proxy = true
proxy_prefix = "/services/oauth2-proxy/oauth2"
{{- end }}
6 changes: 5 additions & 1 deletion helm-charts/basehub/templates/dex/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ spec:
- name: dex
containerPort: 5556
env:
# These are expanded by the dex config
- name: HUB_OAUTH2_CLIENT_SECRET
valueFrom:
secretKeyRef:
Expand All @@ -49,7 +50,9 @@ spec:
mountPath: /srv/config
- name: db
mountPath: /srv/db
command:
# Needs to be args, not cmd - this allows gomplate based
# expansion of config file
args:
- dex
- serve
- /srv/config/dex.yaml
Expand All @@ -65,6 +68,7 @@ spec:
- name: oauth2-proxy
containerPort: 9000
env:
# This is read by oauth2-proxy
- name: OAUTH2_PROXY_COOKIE_SECRET
valueFrom:
secretKeyRef:
Expand Down
17 changes: 17 additions & 0 deletions helm-charts/basehub/templates/static/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{- if .Values.staticSites.enabled -}}
kind: ConfigMap
apiVersion: v1
metadata:
name: static-sites
labels:
app: static-sites
data:
nginx.conf: |
server {
listen 8080;
location {{ .Values.staticSites.path }} {
index index.html;
alias /srv/content/repo;
}
}
{{- end }}
71 changes: 71 additions & 0 deletions helm-charts/basehub/templates/static/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{{- if .Values.staticSites.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: static-sites
spec:
replicas: 1
selector:
matchLabels:
app: static-sites
template:
metadata:
labels:
app: static-sites
annotations:
checksum/config: {{ include (print $.Template.BasePath "/static/configmap.yaml") . | sha256sum }}
spec:
volumes:
- name: nginx-config
configMap:
name: static-sites
- name: content
emptyDir: {}
initContainers:
- name: site-clone
image: alpine/git
args:
- clone
- --depth=1
- --branch={{ .Values.staticSites.branch | required "staticSites.branch is required with staticSite.enabled set to true" }}
- --single-branch
- --
- '{{ .Values.staticSites.repo | required "staticSites.repo is required with staticSites.enabled set to true" }}'
- /srv/content/repo
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: False
readOnlyRootFilesystem: True
volumeMounts:
- name: content
mountPath: /srv/content
containers:
- name: content-sync
image: alpine/git
workingDir: /srv/content
command:
- /bin/sh
args:
- -c
- "while true; do git fetch origin; git reset --hard origin/{{ .Values.staticSites.branch }}; sleep\
\ 5m; done"
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: False
readOnlyRootFilesystem: True
volumeMounts:
- name: content
mountPath: /srv/content
- name: server
image: nginx:1.19
command: ["/usr/sbin/nginx", "-g", "daemon off;"]
ports:
- name: nginx
containerPort: 8080
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx.conf
- name: content
mountPath: /srv/content
{{- end }}
24 changes: 24 additions & 0 deletions helm-charts/basehub/templates/static/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{- if .Values.staticSites.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# Authenticate with oauth2-proxy so only hub logged-in users see this
# https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/
nginx.ingress.kubernetes.io/auth-url: "http://dex.{{ .Release.Namespace }}.svc.cluster.local:9000/services/oauth2-proxy/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/services/oauth2-proxy/oauth2/start?rd=$escaped_request_uri"
name: static-sites
spec:
ingressClassName: nginx
rules:
- host: {{ .Values.staticSites.host}}
http:
paths:
- path: {{ .Values.staticSites.path }}
pathType: Prefix
backend:
service:
name: static-sites
port:
number: 80
{{- end }}
16 changes: 16 additions & 0 deletions helm-charts/basehub/templates/static/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{{- if .Values.staticSites.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: static-sites
labels:
app: static-sites
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: nginx
selector:
app: static-sites
{{- end }}
29 changes: 29 additions & 0 deletions helm-charts/basehub/values.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,36 @@ required:
- jupyterhub
- userServiceAccount
- dex
- staticSites
properties:
staticSites:
type: object
additionalProperties: false
required:
- enabled
properties:
enabled:
type: boolean
description: |
Enable hosting static sites associated with this hub.
repo:
type: string
description: |
Git repo to clone and serve statically
branch:
type: string
description: |
Branch in given git repo to check out after cloning the repo
host:
type: string
description: |
DNS host name of the JupyterHub.
Must match what the JupyterHub and dex are set up with.
path:
type: string
description: |
Absolute path under which the static sites should be available
dex:
type: object
additionalProperties: false
Expand Down
4 changes: 4 additions & 0 deletions helm-charts/basehub/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ userServiceAccount:
dex:
enabled: false

staticSites:
enabled: false
branch: main

azureFile:
enabled: false
pv:
Expand Down

0 comments on commit 878288d

Please sign in to comment.