Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding route dependencies module. #251

Merged
merged 36 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5ee3c2d
Adding route dependencies module.
rhysrevans3 May 10, 2024
10d621e
Fixing pre-commit errors.
rhysrevans3 May 10, 2024
bb04359
Merge branch 'main' into route_dependencies
jonhealy1 May 10, 2024
c2c12bd
Adding to opensearch.
rhysrevans3 May 14, 2024
7b8ef5a
Adding testing.
rhysrevans3 May 14, 2024
aedf077
Merge branch 'main' into route_dependencies
jonhealy1 May 15, 2024
6a36f6b
Allow route dependencies to be passed as a variable for testing.
rhysrevans3 May 15, 2024
19b97f6
Merge branch 'route_dependencies' of github.com:rhysrevans3/stac-fast…
rhysrevans3 May 15, 2024
211d04d
Removing context extension.
rhysrevans3 May 15, 2024
8c14390
Allowing fuctions or class dependencies.
rhysrevans3 May 15, 2024
4b90d15
Updating test conf.
rhysrevans3 May 15, 2024
6891357
Fix for import error.
rhysrevans3 May 15, 2024
d718601
Add test directory to sys path for import.
rhysrevans3 May 15, 2024
a1d3929
Fix for sys path import.
rhysrevans3 May 15, 2024
65d367c
Add test dir to sys path.
rhysrevans3 May 15, 2024
53f17f8
Switching tests to use collections endpoint for rd tests.
rhysrevans3 May 15, 2024
51de3bf
Switch from post to get on test_authenticated.
rhysrevans3 May 15, 2024
ffd3912
Removing unneeded length check.
rhysrevans3 May 16, 2024
bde4b3c
Adding docker compose file and readme help for route dependencies.
rhysrevans3 May 24, 2024
bd29dcd
Merge branch 'main' of github.com:stac-utils/stac-fastapi-elasticsear…
rhysrevans3 Jun 3, 2024
cc1a30e
Adding to changelog.
rhysrevans3 Jun 3, 2024
caa45dd
Merge branch 'main' into route_dependencies
jonhealy1 Jun 11, 2024
fb931bc
Moving basic auth to route dependencies.
rhysrevans3 Jun 12, 2024
c08d25c
Merge branch 'route_dependencies' of github.com:rhysrevans3/stac-fast…
rhysrevans3 Jun 12, 2024
b689275
Removing basic_auth copy.
rhysrevans3 Jun 13, 2024
370b401
Adding route that aren't lists.
rhysrevans3 Jun 13, 2024
6a7308e
Adding schema validation to route dependencies.
rhysrevans3 Jun 17, 2024
a88f04c
pre-commit.
rhysrevans3 Jun 17, 2024
b5231f4
Merge branch 'main' of github.com:stac-utils/stac-fastapi-elasticsear…
rhysrevans3 Jun 17, 2024
deba511
Adding jsonschema install.
rhysrevans3 Jun 17, 2024
e9bba36
Fixing schema.
rhysrevans3 Jun 17, 2024
87a2294
Add docker file example for route_dependencies.json.
rhysrevans3 Jun 17, 2024
9617d39
Merge branch 'main' of github.com:stac-utils/stac-fastapi-elasticsear…
rhysrevans3 Jun 18, 2024
01b0af5
Adding Oauth2 example.
rhysrevans3 Jun 18, 2024
f9314d9
Updating changelog and opensearch auth in compose files.
rhysrevans3 Jun 21, 2024
4ab9d48
Update CHANGELOG.md
jonhealy1 Jun 22, 2024
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Changed
rhysrevans3 marked this conversation as resolved.
Show resolved Hide resolved

- Added route dependency configuration [#251](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/pull/251)

- Updated stac-fastapi libraries to v3.0.0a1 [#265](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/pull/265)
- Updated stac-fastapi libraries to v3.0.0a3 [#269](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/pull/269)

Expand Down
141 changes: 86 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,75 +279,106 @@ The modified Items with lowercase identifiers will now be visible to users acces

#### Environment Variable Configuration

Basic authentication is an optional feature. You can enable it by setting the environment variable `BASIC_AUTH` as a JSON string.
Basic authentication is an optional feature that can be enabled through [Route Dependencies](#route-dependencies).

Example:
```
BASIC_AUTH={"users":[{"username":"user","password":"pass","permissions":"*"}]}
```

### User Permissions Configuration
### Example Configuration

In order to set endpoints with specific access permissions, you can configure the `users` key with a list of user objects. Each user object should contain the username, password, and their respective permissions.

Example: This example illustrates the configuration for two users: an **admin** user with full permissions (*) and a **reader** user with limited permissions to specific read-only endpoints.
This example illustrates the configuration for two users: an **admin** user with full permissions (*) and a **reader** user with limited permissions to specific read-only endpoints.
```json
{
"users": [
{
"username": "admin",
"password": "admin",
"permissions": "*"
},
{
"username": "reader",
"password": "reader",
"permissions": [
{"path": "/", "method": ["GET"]},
{"path": "/conformance", "method": ["GET"]},
{"path": "/collections/{collection_id}/items/{item_id}", "method": ["GET"]},
{"path": "/search", "method": ["GET", "POST"]},
{"path": "/collections", "method": ["GET"]},
{"path": "/collections/{collection_id}", "method": ["GET"]},
{"path": "/collections/{collection_id}/items", "method": ["GET"]},
{"path": "/queryables", "method": ["GET"]},
{"path": "/queryables/collections/{collection_id}/queryables", "method": ["GET"]},
{"path": "/_mgmt/ping", "method": ["GET"]}
]
[
{
"routes": [
{
"method": "*",
"path": "*"
}
],
"dependencies": [
{
"method": "stac_fastapi.core.basic_auth.BasicAuth",
"kwargs": {
"credentials":[
{
"username": "admin",
"password": "admin"
}
]
}
}
]
},
{
"routes": [
{"path": "/", "method": ["GET"]},
{"path": "/conformance", "method": ["GET"]},
{"path": "/collections/{collection_id}/items/{item_id}", "method": ["GET"]},
{"path": "/search", "method": ["GET", "POST"]},
{"path": "/collections", "method": ["GET"]},
{"path": "/collections/{collection_id}", "method": ["GET"]},
{"path": "/collections/{collection_id}/items", "method": ["GET"]},
{"path": "/queryables", "method": ["GET"]},
{"path": "/queryables/collections/{collection_id}/queryables", "method": ["GET"]},
{"path": "/_mgmt/ping", "method": ["GET"]}
],
"dependencies": [
{
"method": "stac_fastapi.core.basic_auth.BasicAuth",
"kwargs": {
"credentials":[
{
"username": "reader",
"password": "reader"
}
]
}
}
]
}
}
]
```

## Route Dependencies

### Public Endpoints Configuration
### Configuration

In order to set endpoints with public access, you can configure the public_endpoints key with a list of endpoint objects. Each endpoint object should specify the path and method of the endpoint.
Route dependencies for endpoints can enable through the `STAC_FASTAPI_ROUTE_DEPENDENCIES`
environment variable as a path to a JSON file or a JSON string.

Example: This example demonstrates the configuration for public endpoints, allowing access without authentication to read-only endpoints.
```json
{
"public_endpoints": [
{"path": "/", "method": "GET"},
{"path": "/conformance", "method": "GET"},
{"path": "/collections/{collection_id}/items/{item_id}", "method": "GET"},
{"path": "/search", "method": "GET"},
{"path": "/search", "method": "POST"},
{"path": "/collections", "method": "GET"},
{"path": "/collections/{collection_id}", "method": "GET"},
{"path": "/collections/{collection_id}/items", "method": "GET"},
{"path": "/queryables", "method": "GET"},
{"path": "/queryables/collections/{collection_id}/queryables", "method": "GET"},
{"path": "/_mgmt/ping", "method": "GET"}
#### Route Dependency

A Route Dependency must include `routes`, a list of at least one [Route](#routes), and `dependencies` a
list of at least one [Dependency](#dependencies).

#### Routes

A Route must include a `path`, the relative path to the endpoint, and a `method`, the request method of the path.

#### Dependencies

A Dependency must include the `method`, a dot seperated path to the Class or Function, and
can include any `args` or `kwargs` for the method.

#### Example
```
STAC_FASTAPI_ROUTE_DEPENDENCIES=[
{
"routes": [
{
"method": "GET",
"path": "/collections"
}
],
"users": [
{
"username": "admin",
"password": "admin",
"permissions": "*"
"dependencies": [
{
"method": "fastapi.security.OAuth2PasswordBearer",
jonhealy1 marked this conversation as resolved.
Show resolved Hide resolved
"kwargs": {
"tokenUrl": "token"
}
}
]
}
}
]
```

### Docker Compose Configurations
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.basic_auth_protected.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ services:
- ES_USE_SSL=false
- ES_VERIFY_CERTS=false
- BACKEND=elasticsearch
- BASIC_AUTH={"users":[{"username":"admin","password":"admin","permissions":"*"},{"username":"reader","password":"reader","permissions":[{"path":"/","method":["GET"]},{"path":"/conformance","method":["GET"]},{"path":"/collections/{collection_id}/items/{item_id}","method":["GET"]},{"path":"/search","method":["GET","POST"]},{"path":"/collections","method":["GET"]},{"path":"/collections/{collection_id}","method":["GET"]},{"path":"/collections/{collection_id}/items","method":["GET"]},{"path":"/queryables","method":["GET"]},{"path":"/queryables/collections/{collection_id}/queryables","method":["GET"]},{"path":"/_mgmt/ping","method":["GET"]}]}]}
- STAC_FASTAPI_ROUTE_DEPENDENCIES=[{"routes":[{"method":"*","path":"*"}],"dependencies":[{"method":"stac_fastapi.core.basic_auth.BasicAuth","kwargs":{"credentials":[{"username":"admin","password":"admin"}]}}]},{"routes":[{"path":"/","method":["GET"]},{"path":"/conformance","method":["GET"]},{"path":"/collections/{collection_id}/items/{item_id}","method":["GET"]},{"path":"/search","method":["GET","POST"]},{"path":"/collections","method":["GET"]},{"path":"/collections/{collection_id}","method":["GET"]},{"path":"/collections/{collection_id}/items","method":["GET"]},{"path":"/queryables","method":["GET"]},{"path":"/queryables/collections/{collection_id}/queryables","method":["GET"]},{"path":"/_mgmt/ping","method":["GET"]}],"dependencies":[{"method":"stac_fastapi.core.basic_auth.BasicAuth","kwargs":{"credentials":[{"username":"reader","password":"reader"}]}}]}]
rhysrevans3 marked this conversation as resolved.
Show resolved Hide resolved
ports:
- "8080:8080"
volumes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ services:
- ES_USE_SSL=false
- ES_VERIFY_CERTS=false
- BACKEND=elasticsearch
- BASIC_AUTH={"public_endpoints":[{"path":"/","method":"GET"},{"path":"/conformance","method":"GET"},{"path":"/collections/{collection_id}/items/{item_id}","method":"GET"},{"path":"/search","method":"GET"},{"path":"/search","method":"POST"},{"path":"/collections","method":"GET"},{"path":"/collections/{collection_id}","method":"GET"},{"path":"/collections/{collection_id}/items","method":"GET"},{"path":"/queryables","method":"GET"},{"path":"/queryables/collections/{collection_id}/queryables","method":"GET"},{"path":"/_mgmt/ping","method":"GET"}],"users":[{"username":"admin","password":"admin","permissions":[{"path":"/","method":["GET"]},{"path":"/conformance","method":["GET"]},{"path":"/collections/{collection_id}/items/{item_id}","method":["GET","POST","PUT","DELETE"]},{"path":"/search","method":["GET","POST"]},{"path":"/collections","method":["GET","PUT","POST"]},{"path":"/collections/{collection_id}","method":["GET","DELETE"]},{"path":"/collections/{collection_id}/items","method":["GET","POST"]},{"path":"/queryables","method":["GET"]},{"path":"/queryables/collections/{collection_id}/queryables","method":["GET"]},{"path":"/_mgmt/ping","method":["GET"]}]}]}
- STAC_FASTAPI_ROUTE_DEPENDENCIES=[{"routes":[{"method":"GET","path":"/collections"}],"dependencies":[{"method":"conftest.must_be_bob"}]}]
ports:
- "8080:8080"
volumes:
Expand Down Expand Up @@ -55,7 +55,7 @@ services:
- ES_USE_SSL=false
- ES_VERIFY_CERTS=false
- BACKEND=opensearch
- BASIC_AUTH={"public_endpoints":[{"path":"/","method":"GET"},{"path":"/conformance","method":"GET"},{"path":"/collections/{collection_id}/items/{item_id}","method":"GET"},{"path":"/search","method":"GET"},{"path":"/search","method":"POST"},{"path":"/collections","method":"GET"},{"path":"/collections/{collection_id}","method":"GET"},{"path":"/collections/{collection_id}/items","method":"GET"},{"path":"/queryables","method":"GET"},{"path":"/queryables/collections/{collection_id}/queryables","method":"GET"},{"path":"/_mgmt/ping","method":"GET"}],"users":[{"username":"admin","password":"admin","permissions":[{"path":"/","method":["GET"]},{"path":"/conformance","method":["GET"]},{"path":"/collections/{collection_id}/items/{item_id}","method":["GET","POST","PUT","DELETE"]},{"path":"/search","method":["GET","POST"]},{"path":"/collections","method":["GET","PUT","POST"]},{"path":"/collections/{collection_id}","method":["GET","DELETE"]},{"path":"/collections/{collection_id}/items","method":["GET","POST"]},{"path":"/queryables","method":["GET"]},{"path":"/queryables/collections/{collection_id}/queryables","method":["GET"]},{"path":"/_mgmt/ping","method":["GET"]}]}]}
- BASIC_AUTH={"users":[{"username":"admin","password":"admin","permissions":"*"},{"username":"reader","password":"reader","permissions":[{"path":"/","method":["GET"]},{"path":"/conformance","method":["GET"]},{"path":"/collections/{collection_id}/items/{item_id}","method":["GET"]},{"path":"/search","method":["GET","POST"]},{"path":"/collections","method":["GET"]},{"path":"/collections/{collection_id}","method":["GET"]},{"path":"/collections/{collection_id}/items","method":["GET"]},{"path":"/queryables","method":["GET"]},{"path":"/queryables/collections/{collection_id}/queryables","method":["GET"]},{"path":"/_mgmt/ping","method":["GET"]}]}]}
rhysrevans3 marked this conversation as resolved.
Show resolved Hide resolved
ports:
- "8082:8082"
volumes:
Expand Down
129 changes: 129 additions & 0 deletions docker-compose.route_dependencies_file.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
version: '3.9'

services:
app-elasticsearch:
container_name: stac-fastapi-es
image: stac-utils/stac-fastapi-es
restart: always
build:
context: .
dockerfile: dockerfiles/Dockerfile.dev.es
environment:
- STAC_FASTAPI_TITLE=stac-fastapi-elasticsearch
- STAC_FASTAPI_DESCRIPTION=A STAC FastAPI with an Elasticsearch backend
- STAC_FASTAPI_VERSION=3.0.0a1
- APP_HOST=0.0.0.0
- APP_PORT=8080
- RELOAD=true
- ENVIRONMENT=local
- WEB_CONCURRENCY=10
- ES_HOST=elasticsearch
- ES_PORT=9200
- ES_USE_SSL=false
- ES_VERIFY_CERTS=false
- BACKEND=elasticsearch
- STAC_FASTAPI_ROUTE_DEPENDENCIES=/app/route_dependencies/route_dependencies.json
ports:
- "8080:8080"
volumes:
- ./stac_fastapi:/app/stac_fastapi
- ./examples/route_dependencies:/app/route_dependencies
- ./scripts:/app/scripts
- ./esdata:/usr/share/elasticsearch/data
depends_on:
- elasticsearch
command:
bash -c "./scripts/wait-for-it-es.sh es-container:9200 && python -m stac_fastapi.elasticsearch.app"

app-opensearch:
container_name: stac-fastapi-os
image: stac-utils/stac-fastapi-os
restart: always
build:
context: .
dockerfile: dockerfiles/Dockerfile.dev.os
environment:
- STAC_FASTAPI_TITLE=stac-fastapi-opensearch
- STAC_FASTAPI_DESCRIPTION=A STAC FastAPI with an Opensearch backend
- STAC_FASTAPI_VERSION=2.1
- APP_HOST=0.0.0.0
- APP_PORT=8082
- RELOAD=true
- ENVIRONMENT=local
- WEB_CONCURRENCY=10
- ES_HOST=opensearch
- ES_PORT=9202
- ES_USE_SSL=false
- ES_VERIFY_CERTS=false
- BACKEND=opensearch
- BASIC_AUTH={"users":[{"username":"admin","password":"admin","permissions":"*"},{"username":"reader","password":"reader","permissions":[{"path":"/","method":["GET"]},{"path":"/conformance","method":["GET"]},{"path":"/collections/{collection_id}/items/{item_id}","method":["GET"]},{"path":"/search","method":["GET","POST"]},{"path":"/collections","method":["GET"]},{"path":"/collections/{collection_id}","method":["GET"]},{"path":"/collections/{collection_id}/items","method":["GET"]},{"path":"/queryables","method":["GET"]},{"path":"/queryables/collections/{collection_id}/queryables","method":["GET"]},{"path":"/_mgmt/ping","method":["GET"]}]}]}
rhysrevans3 marked this conversation as resolved.
Show resolved Hide resolved
ports:
- "8082:8082"
volumes:
- ./stac_fastapi:/app/stac_fastapi
- ./scripts:/app/scripts
- ./osdata:/usr/share/opensearch/data
depends_on:
- opensearch
command:
bash -c "./scripts/wait-for-it-es.sh os-container:9202 && python -m stac_fastapi.opensearch.app"

elasticsearch:
container_name: es-container
image: docker.elastic.co/elasticsearch/elasticsearch:${ELASTICSEARCH_VERSION:-8.11.0}
hostname: elasticsearch
environment:
ES_JAVA_OPTS: -Xms512m -Xmx1g
volumes:
- ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./elasticsearch/snapshots:/usr/share/elasticsearch/snapshots
ports:
- "9200:9200"

opensearch:
container_name: os-container
image: opensearchproject/opensearch:${OPENSEARCH_VERSION:-2.11.1}
hostname: opensearch
environment:
- discovery.type=single-node
- plugins.security.disabled=true
- OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m
volumes:
- ./opensearch/config/opensearch.yml:/usr/share/opensearch/config/opensearch.yml
- ./opensearch/snapshots:/usr/share/opensearch/snapshots
ports:
- "9202:9202"

postgres:
image: postgres:15
container_name: postgres
hostname: keycloakdb
environment:
- POSTGRES_DB=keycloak
- POSTGRES_USER=keycloak
- POSTGRES_PASSWORD=password
volumes:
- postgres:/var/lib/postgresql/data

keycloak:
jonhealy1 marked this conversation as resolved.
Show resolved Hide resolved
image: quay.io/keycloak/keycloak:25.0.0
container_name: keycloak
ports:
- 8083:8083
environment:
- KEYCLOAK_IMPORT=/tmp/keycloak-realm.json
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
- KC_HTTP_PORT=8083
- KC_DB=postgres
- KC_DB_URL=jdbc:postgresql://keycloakdb:5432/keycloak
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD=password
volumes:
- ./example/route_dependencies/stac-realm.json:/opt/keycloak/data/import
command: start-dev --import-realm
depends_on:
- postgres

volumes:
postgres:
50 changes: 50 additions & 0 deletions examples/route_dependencies/route_dependencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[
{
"routes": [
{
"method": "*",
"path": "*"
}
],
"dependencies": [
{
"method": "fastapi.security.OAuth2PasswordBearer",
"kwargs": {
"tokenUrl": "http://keycloak:8083/auth/realms/stac/protocol/openid-connect/token"
}
}
]
},
{
"routes": [
{
"path": "/collections/{collection_id}/items/{item_id}",
"method": "GET"
},
{
"path": "/search",
"method": [
"GET",
"POST"
]
},
{
"path": "/collections",
"method": "GET"
}
],
"dependencies": [
{
"method": "stac_fastapi.core.basic_auth.BasicAuth",
"kwargs": {
"credentials": [
{
"username": "reader",
"password": "reader"
}
]
}
}
]
}
]
Loading