Skip to content

Commit d37cee3

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

File tree

8 files changed

+601
-17
lines changed

8 files changed

+601
-17
lines changed

helm/AUTHORIZATION.md

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