Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
41 changes: 41 additions & 0 deletions charts/eoapi/data/stac-auth-proxy/custom_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Sample custom filters for STAC Auth Proxy.
This file demonstrates the structure needed for custom collection and item filters.
"""

import dataclasses
from typing import Any


@dataclasses.dataclass
class CollectionsFilter:
"""Returns CQL2 filter for /collections endpoint."""

async def __call__(self, context: dict[str, Any]) -> str | dict[str, Any]:
"""
Return format:
- CQL2-text string: "1=1" or "private = false"
- CQL2-JSON dict: {"op": "=", "args": [{"property": "owner"}, "user123"]}

Examples:
- Allow all: return "1=1"
- User-specific: return f"owner = '{context['token']['sub']}'"
- Public only: return "private = false" if not context["token"] else "1=1"
- Complex: return {"op": "in", "args": [{"property": "id"}, ["col1", "col2"]]}
"""
return "1=1"


@dataclasses.dataclass
class ItemsFilter:
"""Returns CQL2 filter for /search and /collections/{id}/items endpoints."""

async def __call__(self, context: dict[str, Any]) -> str | dict[str, Any]:
"""
Examples:
- Allow all: return "1=1"
- Collection-based: return f"collection = '{context['collection_id']}'"
- User-specific: return f"properties.owner = '{context['token']['sub']}'"
- Complex: return {"op": "in", "args": [{"property": "collection"}, approved_list]}
"""
return "1=1"
21 changes: 19 additions & 2 deletions charts/eoapi/profiles/experimental.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,25 @@ ingress:
stac-auth-proxy:
enabled: true
# For testing this will be set dynamically; for production, point to your OIDC server
# env:
# OIDC_DISCOVERY_URL: "http://eoapi-mock-oidc-server.eoapi.svc.cluster.local:8080/.well-known/openid-configuration"
env:
# OIDC_DISCOVERY_URL: "http://eoapi-mock-oidc-server.eoapi.svc.cluster.local:8080/.well-known/openid-configuration"
# Custom filter classes
COLLECTIONS_FILTER_CLS: "stac_auth_proxy.custom_filters:CollectionsFilter"
ITEMS_FILTER_CLS: "stac_auth_proxy.custom_filters:ItemsFilter"

# Custom filters configuration
customFiltersFile: "data/stac-auth-proxy/custom_filters.py"

extraVolumes:
- name: filters
configMap:
name: eoapi-stac-auth-proxy-custom-filters

extraVolumeMounts:
- name: filters
mountPath: /app/src/stac_auth_proxy/custom_filters.py
subPath: custom_filters.py
readOnly: true

######################
# MOCK OIDC SERVER
Expand Down
16 changes: 16 additions & 0 deletions charts/eoapi/templates/core/stac-auth-proxy-filters-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{{- if index .Values "stac-auth-proxy" "enabled" }}
{{- $stacAuthProxy := index .Values "stac-auth-proxy" }}
{{- if and (hasKey $stacAuthProxy "extraVolumes") $stacAuthProxy.extraVolumes }}
{{- $filterFile := $stacAuthProxy.customFiltersFile | default "data/stac-auth-proxy/custom_filters.py" }}
apiVersion: v1
kind: ConfigMap
metadata:
name: eoapi-stac-auth-proxy-custom-filters
labels:
{{- include "eoapi.labels" . | nindent 4 }}
app.kubernetes.io/component: stac-auth-proxy
data:
custom_filters.py: |
{{ .Files.Get $filterFile | indent 4 }}
{{- end }}
{{- end }}
77 changes: 77 additions & 0 deletions charts/eoapi/tests/stac-auth-proxy-filters_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
suite: test stac-auth-proxy custom filters ConfigMap
templates:
- templates/_helpers/core.tpl
- templates/core/stac-auth-proxy-filters-configmap.yaml

tests:
- it: should create ConfigMap when stac-auth-proxy is enabled and extraVolumes is defined
set:
stac-auth-proxy.enabled: true
stac-auth-proxy.extraVolumes:
- name: filters
configMap:
name: test-filters
template: templates/core/stac-auth-proxy-filters-configmap.yaml
asserts:
- isKind:
of: ConfigMap
- equal:
path: metadata.name
value: eoapi-stac-auth-proxy-custom-filters
- isNotEmpty:
path: data

- it: should not create ConfigMap when stac-auth-proxy is disabled
set:
stac-auth-proxy.enabled: false
stac-auth-proxy.extraVolumes:
- name: filters
configMap:
name: test-filters
asserts:
- hasDocuments:
count: 0

- it: should not create ConfigMap when extraVolumes is not defined
set:
stac-auth-proxy.enabled: true
asserts:
- hasDocuments:
count: 0

- it: should have correct labels
set:
stac-auth-proxy.enabled: true
stac-auth-proxy.extraVolumes:
- name: filters
configMap:
name: test-filters
template: templates/core/stac-auth-proxy-filters-configmap.yaml
asserts:
- equal:
path: metadata.labels["app.kubernetes.io/component"]
value: stac-auth-proxy
- exists:
path: metadata.labels["app.kubernetes.io/name"]
- exists:
path: metadata.labels["app.kubernetes.io/instance"]
- exists:
path: metadata.labels["helm.sh/chart"]

- it: should use custom file path when customFiltersFile is specified
set:
stac-auth-proxy.enabled: true
stac-auth-proxy.customFiltersFile: "data/eoepca_filters.py"
stac-auth-proxy.extraVolumes:
- name: filters
configMap:
name: test-filters
template: templates/core/stac-auth-proxy-filters-configmap.yaml
asserts:
- isKind:
of: ConfigMap
- equal:
path: metadata.name
value: eoapi-stac-auth-proxy-custom-filters
- isNotEmpty:
path: data
43 changes: 37 additions & 6 deletions charts/eoapi/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -417,17 +417,48 @@ stac-auth-proxy:
enabled: false
image:
tag: "v0.11.1"
env:
ROOT_PATH: "/stac"
OVERRIDE_HOST: "false"
DEFAULT_PUBLIC: "true"
# UPSTREAM_URL will be set dynamically in template to point to stac service
# OIDC_DISCOVERY_URL must be configured when enabling auth
ingress:
enabled: false # Handled by main eoapi ingress
service:
port: 8080
resources: {}
env:
# OIDC_DISCOVERY_URL must be configured when enabling auth (required)
# UPSTREAM_URL must be set to "http://<release-name>-stac:8080" (required)
ROOT_PATH: "/stac"
OVERRIDE_HOST: "false"
#
# Authentication filters settings:
DEFAULT_PUBLIC: "true" # This enables standard profile for authentication filters
#
# To use custom filters, ALL THREE of the following are required:
# 1. Set filter class environment variables (uncomment lines below)
# 2. Set customFiltersFile path (see below)
# 3. Configure extraVolumes and extraVolumeMounts (see below)
#
# COLLECTIONS_FILTER_CLS: stac_auth_proxy.custom_filters:CollectionsFilter
# ITEMS_FILTER_CLS: stac_auth_proxy.custom_filters:ItemsFilter

# Path to custom filters file (relative to chart root)
# Creates a ConfigMap from this file - required for custom filters
# customFiltersFile: "data/stac-auth-proxy/custom_filters.py"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So to make custom filters work I need to:

  • Define the customFiltersFile
  • Define extraVolumes as specified in the commented out bits
  • Define extraVolumeMounts as shown in the commented out example

Is that roughly accurate? Can we make that a bit more explicit in the docs, that you need to specify customFiltersFile and ALSO specify the extraVolumes and extraVolumeMounts for it to actually work?

I can see that this is slightly awkward for good reason, but I think we could some-how be a little bit clearer in the comments here - does that make sense?

If I'm misunderstanding and you don't actually need extraVolumes and extraVolumeMounts, then ignore this comment :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right, we need all three things.

And you are also right that this should be much better documented. I went over the documentation and tried to make things much clearer.


# Volume referencing the ConfigMap - required for custom filters
extraVolumes: []
# Example (required for custom filters):
# extraVolumes:
# - name: filters
# configMap:
# name: stac-auth-proxy-filters

# Volume mount making filters available to container - required for custom filters
extraVolumeMounts: []
# Example (required for custom filters):
# extraVolumeMounts:
# - name: filters
# mountPath: /app/src/stac_auth_proxy/custom_filters.py
# subPath: custom_filters.py
# readOnly: true

vector:
enabled: true
Expand Down
Loading
Loading