diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d0b1e9814..66ff7162d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -97,9 +97,13 @@ Please see the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest
- Feature: It is now possible to set `propagation_modes` in the `TracingService` config when using
lightstep as the driver. (Thanks to Paul!) ([#4179])
+- Bugfix: When CORS is specified (either in a `Mapping` or in the `Ambassador` `Module`), CORS
+ processing will happen before authentication. This corrects a problem where XHR to authenticated
+ endpoints would fail.
+
[#4179]: https://github.com/emissary-ingress/emissary/pull/4179
-## [2.2.2] TBD
+## [2.2.2] February 25, 2022
[2.2.2]: https://github.com/emissary-ingress/emissary/compare/v2.2.1...v2.2.2
### Emissary-ingress and Ambassador Edge Stack
diff --git a/docs/releaseNotes.yml b/docs/releaseNotes.yml
index 2770fbd6cd..cd55af026e 100644
--- a/docs/releaseNotes.yml
+++ b/docs/releaseNotes.yml
@@ -48,9 +48,15 @@ items:
github:
- title: "#4179"
link: https://github.com/emissary-ingress/emissary/pull/4179
+ - title: CORS now happens before auth
+ type: bugfix
+ body: >-
+ When CORS is specified (either in a Mapping
or in the Ambassador
+ Module
), CORS processing will happen before authentication. This corrects a
+ problem where XHR to authenticated endpoints would fail.
- version: 2.2.2
- date: 'TBD'
+ date: '2022-02-25'
notes:
- title: TLS Secret validation is now opt-in
type: change
diff --git a/python/ambassador/ir/ir.py b/python/ambassador/ir/ir.py
index da2997c7f9..944ffb191b 100644
--- a/python/ambassador/ir/ir.py
+++ b/python/ambassador/ir/ir.py
@@ -377,15 +377,16 @@ def __init__(self, aconf: Config,
IRLogServiceFactory.load_all(self, aconf)
# After the Ambassador and TLS modules are done, we need to set up the
- # filter chains. Note that order of the filters matters. Start with auth,
- # since it needs to be able to override everything...
- self.save_filter(IRAuth(self, aconf))
+ # filter chains. Note that order of the filters matters. Start with CORS,
+ # so that preflights will work even for things behind auth.
- # ...then deal with the non-configurable cors filter...
self.save_filter(IRFilter(ir=self, aconf=aconf,
rkey="ir.cors", kind="ir.cors", name="cors",
config={}))
+ # Next is auth...
+ self.save_filter(IRAuth(self, aconf))
+
# ...then the ratelimit filter...
if self.ratelimit:
self.save_filter(self.ratelimit, already_saved=True)