Skip to content

Commit

Permalink
Merge branch 'main' into 1.1.x
Browse files Browse the repository at this point in the history
  • Loading branch information
f-necas committed Jan 21, 2025
2 parents 43b3837 + 066ccef commit 5d6a576
Show file tree
Hide file tree
Showing 30 changed files with 945 additions and 137 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/backport.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Automatic backport action

on:
pull_request_target:
types: ["closed", "labeled"]

permissions:
contents: write # so it can comment
pull-requests: write # so it can create pull requests

jobs:
backport:
name: Backport PR
if: github.event.pull_request.merged == true && !(contains(github.event.pull_request.labels.*.name, 'backport'))
runs-on: ubuntu-latest
steps:
- name: Backport Action
uses: sqren/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
auto_backport_label_prefix: backport-to-

- name: Info log
if: ${{ success() }}
run: cat ~/.backport/backport.info.log

- name: Debug log
if: ${{ failure() }}
run: cat ~/.backport/backport.debug.log
10 changes: 10 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ jobs:
distribution: 'adopt'
java-version: '21'
cache: 'maven'
server-id: geOrchestra-artifactory
server-username: ARTIFACTORY_USERNAME_REF
server-password: ARTIFACTORY_TOKEN_REF

- name: "Build gateway"
run: make install test
Expand Down Expand Up @@ -80,6 +83,13 @@ jobs:
run: |
docker tag georchestra/gateway:latest ghcr.io/georchestra/georchestra-gateway/gateway:commit-${{ github.sha }}
docker push ghcr.io/georchestra/georchestra-gateway/gateway:commit-${{ github.sha }}
- name: "Publish binaries in artifactory"
run: ./mvnw deploy -Dmaven.test.skip=true
continue-on-error: true
env:
ARTIFACTORY_TOKEN_REF: ${{ secrets.ARTIFACTORY_TOKEN }}
ARTIFACTORY_USERNAME_REF: ${{ secrets.ARTIFACTORY_USERNAME }}

- name: "Remove SNAPSHOT jars from repository"
run: |
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Georchestra application gateway service
# geOrchestra application gateway service

## Features

Expand Down Expand Up @@ -43,7 +43,7 @@ and the additional property sources by means of spring-boot's
make
```
Builds georchestra submodule dependencies, the gateway, runs tests,
Builds geOrchestra submodule dependencies, the gateway, runs tests,
and builds the docker image.
### Build dependencies only
Expand Down
53 changes: 0 additions & 53 deletions docs/custom-error-pages.adoc

This file was deleted.

187 changes: 187 additions & 0 deletions docs/how-to-proxy-an-app.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
= Gateway

image::https://github.com/georchestra/georchestra-gateway/actions/workflows/docker.yml/badge.svg[gateway]

The gateway belongs to geOrchestra core, since it is the component which:

* handles user sessions
* routes requests to webapps
The behavior is controlled by the files from the `<datadir_root>/gateway` folder, which can be found https://github.com/georchestra/datadir/tree/master/gateway[here]

== How-to integrate a new application in geOrchestra ?

The goal here is to benefit from the https://en.wikipedia.org/wiki/Single_sign-on[SSO] feature for the new application without having to use an external authentication process.

=== Ready to launch example

Here ia a https://github.com/georchestra/sample-docker-composition/tree/main/gateway/new-app[ready-to-launch example of a secured application] behind the gateway.

=== Gateway configuration

. *Put application behind the gateway*

The new application has to be proxified by the gateway first.

It can be done in the https://github.com/georchestra/datadir/blob/master/gateway/routes.yaml[routes.yaml] file, which can be found in geOrchestra datadir. Remember: changes in this file requires to restart the gateway.
This file maps public URLs to internal (private) URLs.

To do so, add a new line in the file under `georchestra.gateway.services` in order to map the internal service:

[,yaml]
----
georchestra.gateway.services:
myapp.target: http://localhost:8280/app_path/
----

Then, in order to map the public URL to the internal service, add a new config under `georchestra.cloud.gateway.routes`:

[,yaml]
----
spring:
cloud:
gateway:
routes:
- id: myappname
uri: ${georchestra.gateway.services.myapp.target}
predicates:
- Path=/app_path,/app_path/**
----

* `id` is the name of the route.
* `uri` must point to internal target.
* `predicates` is mostly used with Path predicate, but we can use https://cloud.spring.io/spring-cloud-gateway/multi/multi_gateway-request-predicates-factories.html[other predicates] like Host, Method, etc.

For instance, both combined, the `app_path` path on gateway's host will be routed to http://localhost:8280/app_path".

. Set security rules

Now, imagine your application has a public frontend (`/newapp/frontend`) and a private backend (`/newapp/backend`).
You probably would like to restrict backend access to administrators, or people having a specific role.

This can be done very easily with the https://github.com/georchestra/datadir/blob/master/gateway/gateway.yaml[gateway.yaml] file, also from the geOrchestra datadir.
Here, rules are defined under `georchestra.gateway.services`.

[,yaml]
----
georchestra:
gateway:
services:
nawappbackend:
target: http://localhost:8080/newapp/frontend/
access-rules:
- intercept-url: /newapp/backend/admin*
allowed-roles: ADMINISTRATOR
- intercept-url: /newapp/backend/public*
anonymous: true
newappfrontend:
target: http://localhost:80/newapp/frontend
access-rules:
- intercept-url: /newapp/**
anonymous: true
headers:
proxy: true
username: false
roles: false
org: false
orgname: true
json-user: true
----

=== Application configuration

==== Headers

As you can see above, the `newappfrontend` service has a header section, which is used to override the default headers that will be sent to the frontend application.

In `gateway.yaml` as the start of the file, you can modify the default headers sent to apps:

[,yaml]
----
georchestra:
gateway:
default-headers:
proxy: true
...
json-user: true
----

It is also possible to create a specific role in the console app which grants access to the backend, eg with role `NEWAPP_ADMIN`.

==== How it works

With every request, the geOrchestra gateway adds specific HTTP headers, allowing the application to know:

* if the request comes from a registered user, or an anonymous one - this is `sec-username` (not provided if anonymous).
* which roles the user holds - `sec-roles` is a semi-colon separated list of roles (not provided if anonymous).
* which organisation the user belongs to - `sec-orgname` provides the human-readable organisation title while `sec-org` is mapped onto the organisation id (LDAP's `cn`).

Several other user properties are also provided as headers:

* `sec-proxy` tells that request comes from the proxy
* `sec-email` is the user email
* `sec-firstname` is the first name (LDAP `givenName`)
* `sec-lastname` is the second name (LDAP `sn`)
* `sec-tel` is the user phone number (LDAP `telephoneNumber`)
* `sec-json-user` is a Base64 json representation of the user object.
* `sec-json-organization` is a Base64 json representation of the organization object.

You can also use the https://github.com/georchestra/sample-docker-composition/tree/main/gateway/new-app[ready-to-launch example] to check how headers are sent to the application.

You can find full configuration in https://github.com/georchestra/georchestra-gateway/blob/main/gateway/src/main/java/org/georchestra/gateway/model/HeaderMappings.java[HeaderMappings.java] file. You just need to rename fields from camelCase (in java file) to kebab-case (in yaml file).

See link:./custom_filters.adoc#addsecheadersgatewayfilter[here] for technical details.

The application handles requests appropriately thanks to the headers received.
Some applications will require a direct connection to the LDAP (where users, roles and organisations objects are stored), for instance to list all organisations.

==== Entrypoints

The login entrypoint is `/login` but more generally, one uses the `login` GET parameter in any querystring to force login into a given application.
As a result, the new application may generate links like these: `/newapp/frontend/?login`, for instance if some features in the frontend are only available when authenticated.

Logout entrypoint is `/logout`.
Password recovery form is available from `/console/account/passwordRecovery`.
Account creation form can be found at `/console/account/new`.

==== Cookie Affinity Mapping

Sometimes, cookies sent by one backing service need to be readable by another.
The Gateway will set a cookie path to all backend service cookies to match the service base path (for example,
all cookies sent by the `console` application will have their path set to `/console`.
This makes it impossible for other applications to read them.
A clear case is when the `datahub` application, under the `/datahub` context path, needs access to the
GeoNetwork `XSRF-TOKEN` issued cookie.

*Cookie Affinity Mapping* allows to duplicate cookies set to one path with another path. For the example above,
we need to make it so the GeoNetwork `XSRF-TOKEN` cookie is sent twice to the client, once with `Path=/geonetwork`
and once with `Path=/datahub`.

`gateway.yaml` can be used to configure such cookie affinity. It shall contain an array of objects like the following:

[,yaml]
----
spring:
cloud:
gateway:
routes:
- id: geonetwork
uri: ${georchestra.gateway.services.geonetwork.target}
predicates:
- Path=/geonetwork/**
filters:
- name: CookieAffinity
args:
name: XSRF-TOKEN
from: /geonetwork
to: /datahub
----

The `name` property indicates the cookie name, the `from` property indicates from which original path the cookie
will be duplicated, and the `to` property which path to duplicate the cookie with.

=== Adding georchestra's header to your application

In order to add the georchestra's header to your application, you have to implement a `script` and `<geor-header>` tag in your application.

For full configuration see https://github.com/georchestra/header/[header's repository].
Loading

0 comments on commit 5d6a576

Please sign in to comment.