Security — JupyterLab
The tdp-jupyter chart uses DummyAuthenticator by default (username and password in the values file) and supports optional LDAP via ldapauthenticator.LDAPAuthenticator.
Default authentication
tdp-jupyter:
hub:
config:
JupyterHub:
authenticator_class: dummy
DummyAuthenticator:
username: admin
password: tdp-password
Suitable for development only. Change the password or authentication method in production.
LDAP
LDAP authentication is optional. To enable it, create the bind password Secret and apply the configuration overlay.
Credentials and Secrets
kubectl create secret generic tdp-jupyter-ldap-bind \
--from-literal=LDAP_BIND_PASSWORD='<LDAP_BIND_PASSWORD>' \
-n <NAMESPACE>
LDAP configuration
tdp-jupyter:
hub:
config:
JupyterHub:
authenticator_class: ldapauthenticator.LDAPAuthenticator
LDAPAuthenticator:
server_address: "<LDAP_HOST>"
server_port: 389
tls_strategy: "insecure"
user_attribute: "uid"
bind_dn_template:
- "uid={username},cn=users,cn=accounts,dc=<LDAP_DOMAIN>,dc=<TLD>"
extraConfig:
ldap-config: |
c.Authenticator.allow_all = True
The allow_all block is optional and eases testing. In production, restrict access using allowed_groups or user lists as supported by your JupyterHub version (see the official JupyterHub documentation).
Parameters
| Parameter | Description |
|---|---|
LDAPAuthenticator.server_address | LDAP server address |
LDAPAuthenticator.server_port | LDAP server port |
tls_strategy | TLS mode (e.g. insecure for development) |
bind_dn_template | User DN template |
user_attribute | Login attribute (e.g. uid) |
Single-user server NetworkPolicy
The singleuser.networkPolicy block controls the egress traffic allowed for user notebook pods. By default (enabled: true), the egress rules allow:
tdp-jupyter:
singleuser:
networkPolicy:
enabled: true
egress:
# DNS resolution
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Communication with the Hub (same namespace)
- to:
- namespaceSelector: {}
# Access to IPs outside the cluster (e.g. Ozone S3, external services)
- to:
- ipBlock:
cidr: 0.0.0.0/0
# Spark Master in the same namespace
- to:
- podSelector:
matchLabels:
app.kubernetes.io/component: master
app.kubernetes.io/name: spark
ports:
- protocol: TCP
port: 7077
| Rule | Purpose |
|---|---|
DNS (kube-system, ports 53 UDP/TCP) | Name resolution |
namespaceSelector: {} | Communication with the Hub and other pods in the namespace |
ipBlock: 0.0.0.0/0 | Access to services outside the cluster (Ozone S3G, Trino, Kafka, Hive Metastore, etc.) |
podSelector Spark master (port 7077) | Connection to the Spark cluster when tdpSparkIntegration.enabled: true |
Adjust or restrict egress according to the environment's network policy — for example, replacing 0.0.0.0/0 with more specific ipBlock.cidr values for the S3/Ozone, Trino, or Hive Metastore services used by the notebook.
Ingress (Spark Workers → driver)
In distributed cluster mode, the Spark driver runs inside the notebook pod — it is the Workers that need to open a connection back to it, not the other way around.
For this reason, ingress from Worker pods must be allowed on the driver port (2222) and the block manager port (7777) of the notebook, so that Workers can deliver results back to the driver:
tdp-jupyter:
singleuser:
networkPolicy:
enabled: true
# Allows Spark Workers to connect back to the notebook driver
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/component: worker
app.kubernetes.io/instance: tdp-spark
app.kubernetes.io/name: spark
ports:
- protocol: TCP
port: 2222 # spark.driver.port
- protocol: TCP
port: 7777 # spark.blockManager.port
Without this ingress rule, Workers time out when trying to reach the driver and the Spark application fails with Connecting to /<pod-ip>:2222 timed out.
Troubleshooting
| Problem | Solution |
|---|---|
| LDAP login failure | Check bind_dn_template, connectivity, and server attributes |
| Hub does not start | Validate extraConfig and YAML syntax |
| Spark/S3/Trino connection failure from the notebook | Check singleuser.networkPolicy.egress — traffic may be blocked |
Workers cannot reach the driver (Connecting to /<ip>:2222 timed out) | The single-user pod NetworkPolicy is blocking ingress from Spark Worker pods. Add the ingress rule from the Ingress (Spark Workers → driver) section and upgrade the release |