Skip to content

Commit 985ef13

Browse files
committed
Added helm chart auth options.
1 parent fe75351 commit 985ef13

File tree

8 files changed

+601
-17
lines changed

8 files changed

+601
-17
lines changed

helm/AUTHORIZATION.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Authorization configuration guide
2+
3+
This guide explains how to configure authorization in the STAC Auth Proxy Helm chart.
4+
5+
## Overview
6+
7+
The chart provides two levels of authorization:
8+
9+
1. **[Route-level authorization](https://developmentseed.org/stac-auth-proxy/user-guide/route-level-auth/)**: Controls which API endpoints are accessible and by whom
10+
2. **[Record-level authorization](https://developmentseed.org/stac-auth-proxy/user-guide/record-level-auth/)**: Filters collections and items based on user permissions
11+
12+
## Route-Level Authorization
13+
14+
Configure via `authorization.route` section in `values.yaml`.
15+
16+
### Mode: `default` (Recommended)
17+
18+
Public catalog with protected write operations. This is the most common configuration.
19+
20+
```yaml
21+
authorization:
22+
route:
23+
mode: "default"
24+
```
25+
26+
This automatically sets `DEFAULT_PUBLIC=true`, making all read endpoints public while requiring authentication for write operations.
27+
28+
### Mode: `custom`
29+
30+
Define specific public and private endpoints with custom rules.
31+
32+
```yaml
33+
authorization:
34+
route:
35+
mode: "custom"
36+
publicEndpoints:
37+
"^/collections$": ["GET"]
38+
"^/search$": ["GET", "POST"]
39+
"^/api.html$": ["GET"]
40+
"^/healthz": ["GET"]
41+
privateEndpoints:
42+
"^/collections$": [["POST", "collection:create"]]
43+
"^/collections/([^/]+)$": [["PUT", "collection:update"], ["DELETE", "collection:delete"]]
44+
"^/collections/([^/]+)/items$": [["POST", "item:create"]]
45+
```
46+
47+
**Endpoint format:**
48+
- `publicEndpoints`: Maps regex paths to HTTP methods arrays
49+
- `privateEndpoints`: Maps regex paths to HTTP methods or `[method, scope]` tuples
50+
- Scopes define required OAuth2 scopes for the operation
51+
52+
### Mode: `disabled`
53+
54+
No route-level authorization applied.
55+
56+
```yaml
57+
authorization:
58+
route:
59+
mode: "disabled"
60+
```
61+
62+
## Record-Level Authorization
63+
64+
Configure via `authorization.record` section in `values.yaml`.
65+
66+
### Mode: `disabled` (Default)
67+
68+
No record-level filtering applied. All collections and items are visible to authenticated users.
69+
70+
```yaml
71+
authorization:
72+
record:
73+
mode: "disabled"
74+
```
75+
76+
### Mode: `custom`
77+
78+
Use Python filter classes to control visibility of collections and items.
79+
80+
```yaml
81+
authorization:
82+
record:
83+
mode: "custom"
84+
custom:
85+
filtersFile: "data/custom_filters.py"
86+
```
87+
88+
This automatically:
89+
- Creates a ConfigMap from your Python file
90+
- Mounts it at `/app/src/stac_auth_proxy/custom_filters.py`
91+
- Sets `COLLECTIONS_FILTER_CLS=stac_auth_proxy.custom_filters:CollectionsFilter`
92+
- Sets `ITEMS_FILTER_CLS=stac_auth_proxy.custom_filters:ItemsFilter`
93+
94+
Review the stac-auth-proxy [documentation for more information on custom filters](https://developmentseed.org/stac-auth-proxy/user-guide/record-level-auth/#custom-filter-factories).
95+
96+
### Mode: `opa`
97+
98+
Use Open Policy Agent for policy-based filtering.
99+
100+
```yaml
101+
authorization:
102+
record:
103+
mode: "opa"
104+
opa:
105+
url: "http://opa-service:8181"
106+
policy: "stac/items/allow"
107+
```
108+
109+
This sets:
110+
- `ITEMS_FILTER_CLS=stac_auth_proxy.filters.opa:Opa`
111+
- `ITEMS_FILTER_ARGS='["http://opa-service:8181", "stac/items/allow"]'`
112+
113+
## Some configuration examples
114+
115+
### Example 1: Default for public catalog, protected writes
116+
117+
```yaml
118+
authorization:
119+
route:
120+
mode: "default"
121+
record:
122+
mode: "disabled"
123+
```
124+
125+
### Example 2: Fully protected catalog
126+
127+
```yaml
128+
authorization:
129+
route:
130+
mode: "custom"
131+
publicEndpoints:
132+
"^/healthz": ["GET"]
133+
privateEndpoints:
134+
"^/collections$": [["GET", "stac:read"], ["POST", "stac:write"]]
135+
"^/search$": [["GET", "stac:read"], ["POST", "stac:read"]]
136+
record:
137+
mode: "custom"
138+
custom:
139+
filtersFile: "data/custom_filters.py"
140+
```
141+
142+
## Backward Compatibility
143+
144+
Existing charts using `env` variables directly continue to work:
145+
146+
```yaml
147+
env:
148+
DEFAULT_PUBLIC: "false"
149+
PUBLIC_ENDPOINTS: '{"^/search$": ["GET"]}'
150+
PRIVATE_ENDPOINTS: '{"^/collections$": [["POST", "collection:create"]]}'
151+
ITEMS_FILTER_CLS: "custom.module:Filter"
152+
```
153+
154+
**Environment variables specified in `env` take precedence over `authorization` settings.**

helm/data/custom_filters.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Sample custom filters for STAC Auth Proxy.
3+
This file demonstrates the structure needed for custom collection and item filters.
4+
"""
5+
6+
import dataclasses
7+
from typing import Any
8+
9+
10+
@dataclasses.dataclass
11+
class CollectionsFilter:
12+
"""Filter collections based on user permissions."""
13+
14+
async def __call__(self, context: dict[str, Any]) -> str:
15+
"""Return True if user can access this collection."""
16+
# Example: Allow all collections for authenticated users
17+
return "1=1"
18+
19+
20+
@dataclasses.dataclass
21+
class ItemsFilter:
22+
"""Filter items based on user permissions."""
23+
24+
async def __call__(self, context: dict[str, Any]) -> str:
25+
"""Return True if user can access this item."""
26+
# Example: Allow all items for authenticated users
27+
return "1=1"

helm/templates/_helpers.tpl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,76 @@ Render env var value based on type
6969
{{- . | toJson | quote -}}
7070
{{- end -}}
7171
{{- end -}}
72+
73+
{{/*
74+
Generate authorization environment variables
75+
*/}}
76+
{{- define "stac-auth-proxy.authorizationEnv" -}}
77+
{{- $routeMode := .Values.authorization.route.mode | default "default" -}}
78+
{{- $recordMode := .Values.authorization.record.mode | default "disabled" -}}
79+
80+
{{- /* Route-level authorization */ -}}
81+
{{- if eq $routeMode "default" -}}
82+
{{- if not (hasKey .Values.env "DEFAULT_PUBLIC") }}
83+
- name: DEFAULT_PUBLIC
84+
value: "true"
85+
{{- end }}
86+
{{- else if eq $routeMode "custom" -}}
87+
{{- if not (hasKey .Values.env "DEFAULT_PUBLIC") }}
88+
- name: DEFAULT_PUBLIC
89+
value: "false"
90+
{{- end }}
91+
{{- if and .Values.authorization.route.publicEndpoints (not (hasKey .Values.env "PUBLIC_ENDPOINTS")) }}
92+
- name: PUBLIC_ENDPOINTS
93+
value: {{ .Values.authorization.route.publicEndpoints | toJson | quote }}
94+
{{- end }}
95+
{{- if and .Values.authorization.route.privateEndpoints (not (hasKey .Values.env "PRIVATE_ENDPOINTS")) }}
96+
- name: PRIVATE_ENDPOINTS
97+
value: {{ .Values.authorization.route.privateEndpoints | toJson | quote }}
98+
{{- end }}
99+
{{- end }}
100+
101+
{{- /* Record-level authorization */ -}}
102+
{{- if eq $recordMode "custom" -}}
103+
{{- if not (hasKey .Values.env "COLLECTIONS_FILTER_CLS") }}
104+
- name: COLLECTIONS_FILTER_CLS
105+
value: "stac_auth_proxy.custom_filters:CollectionsFilter"
106+
{{- end }}
107+
{{- if not (hasKey .Values.env "ITEMS_FILTER_CLS") }}
108+
- name: ITEMS_FILTER_CLS
109+
value: "stac_auth_proxy.custom_filters:ItemsFilter"
110+
{{- end }}
111+
{{- else if eq $recordMode "opa" -}}
112+
{{- if not (hasKey .Values.env "ITEMS_FILTER_CLS") }}
113+
- name: ITEMS_FILTER_CLS
114+
value: "stac_auth_proxy.filters:opa.Opa"
115+
{{- end }}
116+
{{- if and (not (hasKey .Values.env "ITEMS_FILTER_ARGS")) .Values.authorization.record.opa }}
117+
- name: ITEMS_FILTER_ARGS
118+
value: {{ list .Values.authorization.record.opa.url .Values.authorization.record.opa.policy | toJson | quote }}
119+
{{- end }}
120+
{{- end }}
121+
{{- end -}}
122+
123+
{{/*
124+
Generate authorization volumes
125+
*/}}
126+
{{- define "stac-auth-proxy.authorizationVolumes" -}}
127+
{{- if and (eq (.Values.authorization.record.mode | default "disabled") "custom") .Values.authorization.record.custom.filtersFile }}
128+
- name: custom-filters
129+
configMap:
130+
name: {{ include "stac-auth-proxy.fullname" . }}-filters
131+
{{- end }}
132+
{{- end -}}
133+
134+
{{/*
135+
Generate authorization volume mounts
136+
*/}}
137+
{{- define "stac-auth-proxy.authorizationVolumeMounts" -}}
138+
{{- if and (eq (.Values.authorization.record.mode | default "disabled") "custom") .Values.authorization.record.custom.filtersFile }}
139+
- name: custom-filters
140+
mountPath: /app/src/stac_auth_proxy/custom_filters.py
141+
subPath: custom_filters.py
142+
readOnly: true
143+
{{- end }}
144+
{{- end -}}

helm/templates/configmap.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{{- if and (eq (.Values.authorization.record.mode | default "disabled") "custom") .Values.authorization.record.custom.filtersFile }}
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: {{ include "stac-auth-proxy.fullname" . }}-filters
6+
labels:
7+
{{- include "stac-auth-proxy.labels" . | nindent 4 }}
8+
data:
9+
custom_filters.py: |
10+
{{ .Files.Get .Values.authorization.record.custom.filtersFile | nindent 4 }}
11+
{{- end }}

helm/templates/deployment.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,21 @@ spec:
3434
resources:
3535
{{- toYaml .Values.resources | nindent 12 }}
3636
env:
37+
{{- include "stac-auth-proxy.authorizationEnv" . | nindent 12 }}
3738
{{- range $key, $value := .Values.env }}
3839
- name: {{ $key }}
3940
value: {{ include "stac-auth-proxy.envValue" $value }}
4041
{{- end }}
42+
volumeMounts:
43+
{{- include "stac-auth-proxy.authorizationVolumeMounts" . | nindent 12 }}
44+
{{- with .Values.extraVolumeMounts }}
45+
{{- toYaml . | nindent 12 }}
46+
{{- end }}
47+
volumes:
48+
{{- include "stac-auth-proxy.authorizationVolumes" . | nindent 8 }}
49+
{{- with .Values.extraVolumes }}
50+
{{- toYaml . | nindent 8 }}
51+
{{- end }}
4152

4253
{{- with .Values.nodeSelector }}
4354
nodeSelector:

0 commit comments

Comments
 (0)