Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
d7d1daa
local polaris testing wip
samlamont Jun 1, 2026
bba57e9
wip
samlamont Jun 4, 2026
d82cfe7
copilot updates for multi-realm generalization
samlamont Jun 5, 2026
d505bab
fixing local deployment
samlamont Jun 10, 2026
c80e968
remove unused manifest
samlamont Jun 16, 2026
720d1f7
[wip] creating polaris principals from keycloak users; enabling jupyt…
samlamont Jun 18, 2026
fb52e3b
add some carry-over planning docs
mgdenno Jul 14, 2026
5b3589e
Merge remote-tracking branch 'origin/main' into 11-apache-polaris-pla…
mgdenno Jul 17, 2026
46cc1c6
cleanup duplicate file
mgdenno Jul 17, 2026
c58a94e
remove duplicate sections
mgdenno Jul 17, 2026
5363d2e
fix naming bug in example/template
mgdenno Jul 17, 2026
065d47d
fix ingress dep
mgdenno Jul 17, 2026
1b8da91
Stabilize Jupyter Polaris flow before AuthManager work
mgdenno Jul 23, 2026
30229c0
this is a test notebook for human testing in jupyter
mgdenno Jul 23, 2026
c3fe966
Add broker contract and Spark AuthManager prototype scaffold
mgdenno Jul 23, 2026
34c4df9
feat(auth): add broker token exchange path and keycloak wiring
mgdenno Jul 24, 2026
377fdda
feat(authmanager): wire broker subject token into spark auth flow
mgdenno Jul 24, 2026
e601125
build(garden): automate authmanager jar staging for spark and jupyter…
mgdenno Jul 24, 2026
dc3cf5f
feat(notebook): add authmanager toggle for spark broker flow
mgdenno Jul 24, 2026
cb3e399
fix duplicate keys
mgdenno Jul 27, 2026
7b402d8
change token lifespan
mgdenno Jul 27, 2026
35008ef
fix bash script
mgdenno Jul 27, 2026
97b05c2
working jupyter polaris auth with refresh
mgdenno Jul 28, 2026
eb8d066
add username/password docs login
mgdenno Jul 28, 2026
a396035
setup initial integration tests for polaris
mgdenno Jul 29, 2026
0db3e1c
make the principal sync optional for individual grants
mgdenno Jul 29, 2026
4540e86
update docs
mgdenno Jul 30, 2026
6db00c1
cleanup unused polaris role for jupyter users
mgdenno Jul 30, 2026
aedd2fa
update spark session utils in teehr and fix tests.
mgdenno Jul 31, 2026
6734c66
Simplify 01_setup_minio_warehouse: remove manual token management, us…
mgdenno Jul 31, 2026
ad150cf
move notebooks to correct dir
mgdenno Aug 1, 2026
d931ff2
add copilot instructions
mgdenno Aug 1, 2026
2c630dd
Fix Polaris auth and Trino catalog config
mgdenno Aug 3, 2026
8472511
Update copilot instructions
mgdenno Aug 3, 2026
a20d124
update garden project template
mgdenno Aug 3, 2026
781d0e5
update teehr version
mgdenno Aug 6, 2026
1b15ed3
add env remote warehouse id to jupyter
mgdenno Aug 18, 2026
e3013aa
update to skip lfs
mgdenno Aug 18, 2026
e858890
skip lfs
mgdenno Aug 18, 2026
3743af6
add aws keys to local jupyter for dev
mgdenno Aug 19, 2026
000578d
add a teehr project id to local jupyter
mgdenno Aug 19, 2026
7aef8ca
Merge remote-tracking branch 'origin/main' into 11-apache-polaris-pla…
mgdenno Aug 19, 2026
a56e481
comment out xpublish
mgdenno Aug 19, 2026
10bd7ce
comment xpublish
mgdenno Aug 19, 2026
e50c385
remove authmanager jar handlng in favor of the package
mgdenno Aug 19, 2026
f066798
cleanup old authmanager code
mgdenno Aug 20, 2026
851547c
update docs
mgdenno Aug 20, 2026
8da14aa
add encryption to delegated tokens
mgdenno Aug 20, 2026
1a883cb
leave api_keys in keycloak but move delegated session to teehr-api
mgdenno Aug 20, 2026
a4b5985
updates to use polaris sts
mgdenno Aug 21, 2026
3dd2177
remove keycloak-local-users mount from botstrap
mgdenno Aug 24, 2026
309eae2
fix: stop advertising unsupported s3.remote-signing-enabled to clients
mgdenno Aug 25, 2026
4979178
fix: remove vestigial IRSA annotation from jupyter service account
mgdenno Aug 26, 2026
c85a395
uncomment xpublish to add back to deployment
mgdenno Aug 26, 2026
539b52c
remove unused spark-polaris Keycloak client
mgdenno Aug 27, 2026
3332ca7
fix 3 broker security gaps in the delegated-session flow
mgdenno Aug 27, 2026
5f3e762
add automated cluster-mode executor AuthManager test
mgdenno Aug 27, 2026
00775de
fix KeyError: TEEHR_SPARK_IMAGE in new executor test
mgdenno Aug 27, 2026
79ccfa4
change test SA
mgdenno Aug 27, 2026
a6f2db9
fix executor test: kubernetes-pod type for SA control + warehouse def…
mgdenno Aug 27, 2026
b7fcd88
remove minio spark session util useage. Not needed anymore.
mgdenno Aug 27, 2026
0233830
fix REMOTE_WAREHOUSE_IDENTIFIER after switch off create_minio_spark_s…
mgdenno Aug 27, 2026
c692128
fix 4 issues: OpenAPI docs, broker error shape, principal sync, acces…
mgdenno Aug 27, 2026
5eadf1a
make small test commit to submod.
mgdenno Aug 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Context:
- the `teehr` repo which is a python library that contains the scientific code for the teehr environment. This contains code to fetch, validate, store, and analyze hydrologic forecast and simulation data against observations. It works on the concept of an Evaluation which references either a local or remote warehouse and a relates spark session.
- the `teehr-cloud-core` repo contains the main shared teehr-cloud components such as authentication, jupyterhub, Apache Iceberg warehouse, web api, Trino query engine, spark-executors, prefect server, etc. teehr-cloud-core utilizes the teehr library.
- the `teehr-cloud-platform` repo contains terraform IaC for creating an AWS environment that can host a teehr-cloud deployment.
- the `teehr-hub` and `teehr-fved` repos have `teehr-cloud-core` as a submodule and are deployments of `teehr` and `teehr-cloud-core`. They also contain deployment specific components such as frontend dashboards, deployment specific prefect workflows and warehouse setup and maintenance code, certificates, etc.

Don't make any changes in the `teehr-cloud-core` submodules to `teehr-hub` and `teehr-fved`. Only make changes in the `teehr-cloud-core` repo and then update the submodules in the deployments.

Make all changes to the cluster via code. Running one-off commands via kubectl or other tools is not allowed. All changes must be made via code and then applied to the cluster via CI/CD pipelines. This ensures that all changes are tracked in version control and can be rolled back if necessary.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,6 @@ Now the fun of adding new features and bug fixes starts.
When working on the API or the frontend it is convenient to have code syncing. Code syncing can be done in `garden` by running:
```bash
garden deploy --sync
```
```

test commit.
13 changes: 12 additions & 1 deletion api/manifests/configmap.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,18 @@ data:
KEYCLOAK_ISSUER_URL: "https://auth.${var.hostname}/realms/teehr"
KEYCLOAK_JWKS_URL: "http://keycloak-service:8080/realms/teehr/protocol/openid-connect/certs"
KEYCLOAK_AUDIENCE: "teehr-api"
KEYCLOAK_ALLOWED_AUDIENCES: "teehr-api,teehr-frontend"
KEYCLOAK_ALLOWED_AUDIENCES: "teehr-api,teehr-frontend,jupyterhub"
BROKER_TOKEN_EXCHANGE_ENABLED: "true"
BROKER_TOKEN_ENDPOINT: "http://keycloak-service:8080/realms/teehr/protocol/openid-connect/token"
BROKER_OAUTH_CLIENT_ID: "teehr-api"
BROKER_OAUTH_CLIENT_SECRET: ""
BROKER_TARGET_AUDIENCE: "account"
BROKER_DEFAULT_SCOPE: "openid profile email"
BROKER_MIN_TTL_SECONDS: "120"
BROKER_MAX_TTL_SECONDS: "900"
BROKER_REQUEST_TIMEOUT_SECONDS: "10"
BROKER_SUBJECT_CLIENT_ID: "jupyterhub"
BROKER_DELEGATED_SESSION_TTL_SECONDS: "43200"
ANON_RATE_LIMIT_RPM: "20"
AUTH_RATE_LIMIT_RPM: "120"
ROW_LIMIT_ANON: "200"
Expand Down
91 changes: 91 additions & 0 deletions api/manifests/deployment.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,76 @@ spec:
configMapKeyRef:
name: teehr-api-config
key: KEYCLOAK_ALLOWED_AUDIENCES
- name: BROKER_TOKEN_EXCHANGE_ENABLED
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_TOKEN_EXCHANGE_ENABLED
- name: BROKER_TOKEN_ENDPOINT
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_TOKEN_ENDPOINT
- name: BROKER_OAUTH_CLIENT_ID
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_OAUTH_CLIENT_ID
- name: BROKER_OAUTH_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: teehr-api-secrets
key: client-secret
- name: BROKER_TARGET_AUDIENCE
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_TARGET_AUDIENCE
- name: BROKER_DEFAULT_SCOPE
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_DEFAULT_SCOPE
- name: BROKER_MIN_TTL_SECONDS
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_MIN_TTL_SECONDS
- name: BROKER_MAX_TTL_SECONDS
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_MAX_TTL_SECONDS
- name: BROKER_REQUEST_TIMEOUT_SECONDS
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_REQUEST_TIMEOUT_SECONDS
- name: BROKER_SUBJECT_CLIENT_ID
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_SUBJECT_CLIENT_ID
- name: BROKER_DELEGATED_SESSION_TTL_SECONDS
valueFrom:
configMapKeyRef:
name: teehr-api-config
key: BROKER_DELEGATED_SESSION_TTL_SECONDS
- name: BROKER_SUBJECT_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: jupyterhub
key: OAUTH_CLIENT_SECRET
- name: BROKER_SESSION_SIGNING_SECRET
valueFrom:
secretKeyRef:
name: broker-secrets
key: session-signing-secret
- name: BROKER_REFRESH_TOKEN_ENCRYPTION_SECRET
valueFrom:
secretKeyRef:
name: broker-secrets
key: refresh-token-encryption-secret
- name: API_KEYS_DB_HOST
value: keycloak-pg
- name: API_KEYS_DB_PORT
Expand All @@ -97,6 +167,27 @@ spec:
key: password
- name: API_KEYS_DB_DSN
value: "postgresql://$(API_KEYS_DB_USER):$(API_KEYS_DB_PASSWORD)@$(API_KEYS_DB_HOST):$(API_KEYS_DB_PORT)/$(API_KEYS_DB_NAME)"
- name: DELEGATED_SESSIONS_DB_HOST
value: keycloak-pg
- name: DELEGATED_SESSIONS_DB_PORT
value: "5432"
- name: DELEGATED_SESSIONS_DB_NAME
valueFrom:
secretKeyRef:
name: teehr-api-db-secrets
key: database
- name: DELEGATED_SESSIONS_DB_USER
valueFrom:
secretKeyRef:
name: teehr-api-db-secrets
key: username
- name: DELEGATED_SESSIONS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: teehr-api-db-secrets
key: password
- name: DELEGATED_SESSIONS_DB_DSN
value: "postgresql://$(DELEGATED_SESSIONS_DB_USER):$(DELEGATED_SESSIONS_DB_PASSWORD)@$(DELEGATED_SESSIONS_DB_HOST):$(DELEGATED_SESSIONS_DB_PORT)/$(DELEGATED_SESSIONS_DB_NAME)"
- name: ANON_RATE_LIMIT_RPM
valueFrom:
configMapKeyRef:
Expand Down
18 changes: 18 additions & 0 deletions api/src/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class AuthIdentity:
auth_type: str
roles: list[str] = field(default_factory=list)
scopes: list[str] = field(default_factory=list)
preferred_username: str | None = None
groups: list[str] = field(default_factory=list)

@property
def is_authenticated(self) -> bool:
Expand Down Expand Up @@ -129,11 +131,17 @@ async def validate(self, token: str) -> AuthIdentity:
if not subject:
raise HTTPException(status_code=401, detail="JWT missing subject")

groups = claims.get("groups", [])
if not isinstance(groups, list):
groups = []

return AuthIdentity(
subject=subject,
auth_type="jwt",
roles=roles,
scopes=scopes,
preferred_username=claims.get("preferred_username"),
groups=[str(group) for group in groups],
)
except httpx.HTTPError as exc:
logger.error("Keycloak connectivity error during token validation: %s", str(exc))
Expand Down Expand Up @@ -172,6 +180,16 @@ async def get_request_identity(request: Request) -> AuthIdentity:
return identity


def extract_bearer_token_from_request(request: Request) -> str:
auth_header = request.headers.get("authorization", "")
if not auth_header.lower().startswith("bearer "):
raise HTTPException(status_code=401, detail="Bearer token required")
token = auth_header.split(" ", 1)[1].strip()
if not token:
raise HTTPException(status_code=401, detail="Bearer token required")
return token


async def get_authenticated_identity(
identity: AuthIdentity = Depends(get_request_identity),
) -> AuthIdentity:
Expand Down
Loading