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
2 changes: 1 addition & 1 deletion .bumpversion.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tool.bumpversion]
current_version = "2.18.9"
current_version = "2.18.10"
commit = true
tag = false
tag_name = "{new_version}"
Expand Down
52 changes: 52 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,58 @@

[//]: # (list changes here, using '-' for each new entry, remove this when items are added)

[2.18.10](https://github.com/bird-house/birdhouse-deploy/tree/2.18.10) (2025-11-12)
------------------------------------------------------------------------------------------------------------------

## Changes

- Allow each service to specify values for `Access-Control-Allow-Origin`

Previously, if a `location` block in the `nginx` configuration for a given service included the cors helper
configuration (with `include /etc/nginx/conf.d/cors.include;`) then all origins were allowed by default.

This was done by setting the header `Access-Control-Allow-Origin: *` which works well but is a bit too permissive
since it allowed __all__ origins.

This change introduces a mechanism to specify specific additional allowed origins by setting the
`$access_control_allow_origin` nginx variable in the `location` block before including the `cors.include` file.

For example:

```shell
set $access_control_allow_origin http://example.com;
include /etc/nginx/conf.d/cors.include;
```

will set the value of the `Access-Control-Allow-Origin` response header to `http://example.com`.

By default, the header value will be `*` if `$access_control_allow_origin` is not set (to maintain backwards
compatibility).

To specify multiple allowed origins, use a `map` directive (see the implementation for `components/stac` for an
example).

- Set allowed CORS origins for `stac` through an environment variable

This change implements this flexibility for the `components/stac` component. By setting the `STAC_CORS_ORIGINS`
variable a user can specify allowed origins for responses from the `components/stac` component.

For example, setting the following:

```shell
export STAC_CORS_ORIGINS='https://example.com ~^https?://(www\.)?other\.example\.com$'
```

then requests from https://example.com and http://other.example.com will get a response with the
`Access-Control-Allow-Origin header` set to their origin, but http://example.ca will not.

Note that this breaks backwards compatibility slightly since previously all origins were allowed for `/stac` by
default. To match all origins and keep the backwards compatible behaviour you can set:

```shell
export STAC_CORS_ORIGINS='~.*'
```

[2.18.9](https://github.com/bird-house/birdhouse-deploy/tree/2.18.9) (2025-11-10)
------------------------------------------------------------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ override BIRDHOUSE_MAKE_DIR := $(shell realpath -P $$(dirname $(BIRDHOUSE_MAKE_C
# Generic variables
override SHELL := bash
override APP_NAME := birdhouse-deploy
override APP_VERSION := 2.18.9
override APP_VERSION := 2.18.10

# utility to remove comments after value of an option variable
override clean_opt = $(shell echo "$(1)" | $(_SED) -r -e "s/[ '$'\t'']+$$//g")
Expand Down
8 changes: 4 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ for a full-fledged production platform.
* - citation
- | |citation|

.. |commits-since| image:: https://img.shields.io/github/commits-since/bird-house/birdhouse-deploy/2.18.9.svg
.. |commits-since| image:: https://img.shields.io/github/commits-since/bird-house/birdhouse-deploy/2.18.10.svg
:alt: Commits since latest release
:target: https://github.com/bird-house/birdhouse-deploy/compare/2.18.9...master
:target: https://github.com/bird-house/birdhouse-deploy/compare/2.18.10...master

.. |latest-version| image:: https://img.shields.io/badge/tag-2.18.9-blue.svg?style=flat
.. |latest-version| image:: https://img.shields.io/badge/tag-2.18.10-blue.svg?style=flat
:alt: Latest Tag
:target: https://github.com/bird-house/birdhouse-deploy/tree/2.18.9
:target: https://github.com/bird-house/birdhouse-deploy/tree/2.18.10

.. |readthedocs| image:: https://readthedocs.org/projects/birdhouse-deploy/badge/?version=latest
:alt: ReadTheDocs Build Status (latest version)
Expand Down
2 changes: 1 addition & 1 deletion RELEASE.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.18.9 2025-11-10T17:14:06Z
2.18.10 2025-11-12T17:25:51Z
55 changes: 43 additions & 12 deletions birdhouse/components/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -698,31 +698,62 @@ information.
Usage
-----

The STAC API can be browsed via the ``stac-browser`` component. By default, the browser will point to the STAC API
exposed by the current stack instance. Once this component is enabled, STAC API will be accessible at
``https://<BIRDHOUSE_FQDN_PUBLIC>/stac`` endpoint and the STAC browser will be available at
``https://<BIRDHOUSE_FQDN_PUBLIC>/stac-browser`` endpoint. In order to make the STAC browser the default entrypoint,
define the following in the ``env.local`` file::

export BIRDHOUSE_PROXY_ROOT_LOCATION='return 302 ${BIRDHOUSE_PROXY_SCHEME}://\$host/stac-browser;'
The STAC API can be browsed via the ``stac-browser`` component. Once this component is enabled, STAC API
will be accessible at the ``https://<BIRDHOUSE_FQDN_PUBLIC>/stac``.

Here is a sample search query using a CLI::
Here is a sample search query using a the ``pystac-client`` python CLI:

.. code-block:: shell

pip install pystac-client
stac-client search $PAVIS_FQDN/stac -q "variable_id=txgt_32" "scenario=ssp585"
stac-client search $BIRDHOUSE_FQDN_PUBLIC/stac -q "variable_id=txgt_32" "scenario=ssp585"

Calls to the STAC API pass through Twitcher in order to validate authorization. Unauthenticated users will have
read-only access by default to STAC API resources while members of the `stac-admin` group can create and modify
resources. STAC Browser is not protected by any authorization mechanism.
Copy link
Collaborator

Choose a reason for hiding this comment

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

"STAC Browser is not protected by any authorization mechanism", this part is not true anymore, that's why it is removed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's technically true but it's misleading. Access to the stac-browser endpoint is not checked by twitcher but if the user doesn't have permissions to read the stac data (because the stac endpoint is protected by twitcher) then the stac-browser page shows a 403 error anyway.

So from the user's perspective it is protected by an authorization mechanism, it's the same one that protects the stac endpoint.

Calls to the STAC API pass through Twitcher in order to validate authorization.
By default, only users that belong to the ``administrator`` and ``stac-admin`` groups will have access to STAC
endpoints. Additional access permissions can be set in ``Magpie`` as needed.
To give unauthenticated users read-only access to STAC API resources, enable the ``optional-components/stac-public-access``
component.

How to Enable the Component
---------------------------

- Edit ``env.local`` (a copy of `env.local.example`_)
- Add ``./components/stac`` to ``BIRDHOUSE_EXTRA_CONF_DIRS``.

STAC Browser
============

STAC Browser is a web UI used to interact with the STAC API.

Usage
-----

The STAC API can be browsed via the ``stac-browser`` component. By default, the browser will point to the STAC API
exposed by the current ``components/stac`` service.
Once this component is enabled, the STAC browser will be available at the ``https://<BIRDHOUSE_FQDN_PUBLIC>/stac-browser``
endpoint

If your STAC API contains geojson data, it is recommended to set the ``STAC_CORS_ORIGINS`` value to accept the origin
``https://geojson.io`` since the STAC Browser offers a link to open geojson data at this URL.
Note that you do not need to change the ``STAC_CORS_ORIGINS`` value from the default (which accepts all origins), but
if you have changed it please update it to include this origin as well.

For example:

.. code::shell

# If the STAC_CORS_ORIGINS is currently
export STAC_CORS_ORIGINS='http://example.com ~http:(www|other)\.api\.example\.com'

# you can update it to
export STAC_CORS_ORIGINS='http://example.com ~http:(www|other)\.api\.example\.com https://geojson.io'

How to Enable the Component
---------------------------

- Edit ``env.local`` (a copy of `env.local.example`_)
- Add ``./components/stac-browser`` to ``BIRDHOUSE_EXTRA_CONF_DIRS``.

Canarie-API
===========

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ SERVICES = {
# NOTE:
# Below version and release time auto-managed by 'make VERSION=x.y.z bump'.
# Do NOT modify it manually. See 'Tagging policy' in 'birdhouse/README.rst'.
'version': '2.18.9',
'releaseTime': '2025-11-10T17:14:06Z',
'version': '2.18.10',
'releaseTime': '2025-11-12T17:25:51Z',
'institution': '${BIRDHOUSE_INSTITUTION}',
'researchSubject': '${BIRDHOUSE_SUBJECT}',
'supportEmail': '${BIRDHOUSE_SUPPORT_EMAIL}',
Expand Down Expand Up @@ -141,8 +141,8 @@ PLATFORMS = {
# NOTE:
# Below version and release time auto-managed by 'make VERSION=x.y.z bump'.
# Do NOT modify it manually. See 'Tagging policy' in 'birdhouse/README.rst'.
'version': '2.18.9',
'releaseTime': '2025-11-10T17:14:06Z',
'version': '2.18.10',
'releaseTime': '2025-11-12T17:25:51Z',
'institution': '${BIRDHOUSE_INSTITUTION}',
'researchSubject': '${BIRDHOUSE_SUBJECT}',
'supportEmail': '${BIRDHOUSE_SUPPORT_EMAIL}',
Expand Down
18 changes: 15 additions & 3 deletions birdhouse/components/proxy/conf.d/cors.include
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
proxy_hide_header 'Access-Control-Allow-Origin';

if ( $access_control_allow_origin ~ "^$" ) {
set $access_control_allow_origin '*';
}

set $vary_origin ""; # nginx will omit this header value if set to the empty string
if ( $access_control_allow_origin != '*' ) {
set $vary_origin Origin;
}

if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Origin' $access_control_allow_origin;
add_header Vary $vary_origin;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
Expand All @@ -16,13 +26,15 @@
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Origin' $access_control_allow_origin;
add_header Vary $vary_origin;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Origin' $access_control_allow_origin;
add_header Vary $vary_origin;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
Expand Down
2 changes: 2 additions & 0 deletions birdhouse/components/proxy/conf.d/frontend.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ map $http_x_forwarded_proto $real_scheme {
'' $scheme;
}

include /etc/nginx/conf.extra-directives.d/*/*.conf;

server {
listen 80 ${PROXY_LISTEN_80_PARAMS};
server_name localhost;
Expand Down
1 change: 1 addition & 0 deletions birdhouse/components/stac/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
config/magpie/config.yml
config/proxy/conf.extra-service.d/stac.conf
config/proxy/conf.extra-directives.d/stac.conf
config/canarie-api/canarie_api_monitoring.py
service-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ permissions:
# create a default 'stac' resource under 'stac' service
# because of the '/stac/stac' path prefix required to resolve the API links properly,
# all permissions must be nested under this 'stac' resource for requests and permissions to be resolved accordingly
- service: stac
resource: /stac
permission: write
group: stac-admin # create a stac-admin group that can read/write to all stac endpoints
action: create
- service: stac
resource: /stac
permission: read
group: administrator # they already have access, just using admins to create the resource by default
group: stac-admin
action: create
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
map $http_origin $stac_origin_allowed {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remind me what the Nginx map directive do again?

This block means if the http_origin variable exists, create stac_origin_allowed variable with value ${BIRDHOUSE_PROXY_SCHEME}://${BIRDHOUSE_FQDN_PUBLIC}; ${STAC_ADDITIONAL_CORS_ORIGINS} ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's mostly right...

This block creates a new variable stac_origin_allowed whose value is based on the value of the http_origin variable.
If the value of http_origin matches any of the patterns defined in ${STAC_ADDITIONAL_CORS_ORIGINS} then the stac_origin_allowed value will be set to http_origin.
Otherwise stac_origin_allowed will be set to ${BIRDHOUSE_PROXY_SCHEME}://${BIRDHOUSE_FQDN_PUBLIC} (the default).

# default should not be set to the empty string because the cors.include file will interpret
# that as "unset" and will change it to * by default. To get around this, set this to birdhouse's
# own origin (which has the same effect as being unset since same-origin requests are already allowed).
default ${BIRDHOUSE_PROXY_SCHEME}://${BIRDHOUSE_FQDN_PUBLIC};
${STAC_ADDITIONAL_CORS_ORIGINS}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_buffering off;
set $access_control_allow_origin $stac_origin_allowed;
include /etc/nginx/conf.d/cors.include;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ services:
volumes:
- ./components/stac/service-config.json:/static/services/stac.json:ro
- ./components/stac/config/proxy/conf.extra-service.d:/etc/nginx/conf.extra-service.d/stac:ro
- ./components/stac/config/proxy/conf.extra-directives.d:/etc/nginx/conf.extra-directives.d/stac:ro
13 changes: 13 additions & 0 deletions birdhouse/components/stac/default.env
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ export STAC_POPULATOR_BACKUP_IMAGE='${STAC_POPULATOR_BACKUP_DOCKER}:${STAC_POPUL
# This must match the "stac_version" value in the current STAC catalog.
export PYSTAC_STAC_VERSION_OVERRIDE=1.0.0

# Add additional origins that are allowed to access the /stac endpoint (other than the same origin) according to CORS rules.
# The values in the space delimited list set by STAC_CORS_ORIGINS are origins that will be allowed to access responses
# from /stac. These values can either be strings which will be matched directly or regular expressions prefixed by ~.
#
# For example, if STAC_CORS_ORIGINS='https://example.com ~^https?://(www\.)?other\.example\.com$' then requests from
# https://example.com and http://other.example.com will get a response with the Access-Control-Allow-Origin header set
# to their origin, but http://example.ca will not.
# By default all origins are allowed. Set STAC_CORS_ORIGINS in the local environment file to limit the allowed origins.
export STAC_CORS_ORIGINS="~.*"
export STAC_ADDITIONAL_CORS_ORIGINS='$(for origin in $STAC_CORS_ORIGINS; do echo "$origin \$http_origin;"; done;)'

# add any new variables not already in 'VARS' or 'OPTIONAL_VARS' that must be replaced in templates here
# single quotes are important in below list to keep variable names intact until 'birdhouse-compose' parses them
EXTRA_VARS='
Expand All @@ -71,6 +82,7 @@ export DELAYED_EVAL="
STAC_MIGRATION_DOCKER
STAC_MIGRATION_IMAGE
STAC_POPULATOR_BACKUP_IMAGE
STAC_ADDITIONAL_CORS_ORIGINS
"

OPTIONAL_VARS="
Expand All @@ -86,4 +98,5 @@ OPTIONAL_VARS="
\$STAC_MIGRATION_TAGGED
\$STAC_MIGRATION_DOCKER
\$STAC_MIGRATION_IMAGE
\$STAC_ADDITIONAL_CORS_ORIGINS
"
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,3 @@ permissions:
permission: write-match
group: anonymous
action: create

- service: stac
resource: /stac
permission: write
group: stac-admin
action: create
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@
# built documents.
#
# The short X.Y version.
version = '2.18.9'
version = '2.18.10'
# The full version, including alpha/beta/rc tags.
release = '2.18.9'
release = '2.18.10'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
Loading