Skip to content
This repository has been archived by the owner on Sep 13, 2023. It is now read-only.

Add juju config and logic for creating traefik routes #3

Closed
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,36 @@ This charm is used to configure and integrate downstream applications with Charm

Please note that this charm is currently work in progress.

## Usage
## Deployment

```bash
To deploy this charm, run:
```commandline
juju deploy oathkeeper-configurator
```

You can follow the deployment status with `watch -c juju status --color`.

## Configuration

<!-- TODO: Expand once juju configs are in place -->
This charm requires `access_rules` and `root_url` config options to be provided. To set them up, run:
```commandline
juju config oathkeeper-configurator access_rules=@access_rules.json root_url=http://foo.bar/{{juju_model}}-{{juju_unit}}
```
where `access_rules.json` is a json-formatted file that contains the Oathkeeper access rules.

Learn more about access rules [here](https://www.ory.sh/docs/oathkeeper/api-access-rules).

<!-- TODO: Add a note about action to get urls once IAM-427 is done -->

## Integrations

<!-- TODO: Expand once integrations are in place -->
This charm provides an `ingress-per-unit` relation using the `ingress_per_unit` relation interface, with limit 1.
This relation is required to set up ingress routes for charmed workloads.

To integrate a charm using this interface, run:
```commandline
juju integrate oathkeeper-configurator <your-charm>
```

## Security

Expand Down
4 changes: 4 additions & 0 deletions charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ bases:
run-on:
- name: "ubuntu"
channel: "22.04"
parts:
charm:
charm-binary-python-packages:
- jsonschema
76 changes: 76 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Copyright 2023 Canonical Ltd.
# See LICENSE file for licensing details.

options:
access_rules:
description: |
A string containing access rules in json format.
The config value can point to a file if prepended with @.
Example: `access_rules=@access_rules.json`
type: string
headers:
description: |
Comma separated list of headers expected to be returned by Oathkeeper.
Example: `headers=X-User,X-Header`
type: string
default: X-User
rule:
default:
description: |
A Traefik routing rule, see https://doc.traefik.io/traefik/routing/routers/ for
an overview.

The value of the field is going to be processed as a Jinja2 template, with the
following globals available:
- {{juju_model}} resolves to the model name of the downstream proxied
application.
- {{juju_application}} resolves to the application name of the downstream
proxied application.
- {{juju_unit}} resolves to the unit name of the downstream proxied unit;
to avoid issues when used together with the Host directive or similar,
the slash character between application name and unit index is replaced by a dash.

For example, given a downstream unit called `prometheus/0` in the `cos` model, the following:

Host(`foo.bar/{{juju_unit}}-{{juju_model}}`)

would evaluate to:

Host(`foo.bar/cos-prometheus-0`)

If the host is omitted, but the root_url is provided, the charm will
extract the hostname from the url and generate a Host rule for you.
root_url=`http://{{juju_unit}}.bar.baz:80/qux`
--> rule=Host(`{{juju_unit}}.bar.baz`)
type: string
Comment on lines +17 to +45
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure why those are needed, shouldn't we get those from a relation??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The rule will be generated from root_url if the first is not provided (with the globals coming from the relation), although if an admin wants to configure the rules differently, this config option provides that possibility. I'm trying to follow the logic of traefik-route-k8s here as the charm is tested against edge cases.
It's also a ground for non-charmed workloads as I imagine the rules will have to be supplied via config.

root_url:
description: |
The url to advertise to the unit in need of ingress.

The value of the field is going to be processed in exactly the same way as
the `rule` field. The assumption is that the url is going to match
the rule; however, we have no way to validate and/or enforce this condition;
so beware!
For example, given a downstream unit called `prometheus/0` in the `cos` model, the
following configuration is valid:

rule="Host(`{{juju_unit}}.{{juju_model}}.foo.bar`)"
root_url="http://{{juju_unit}}.{{juju_model}}.foo.bar/baz"

while the following configuration is not:

rule="Host(`{{juju_model}}-{{juju_unit}}.foo.bar`) ||
HostRegexp(`{subdomain:[a-z]+}.foo.bar`) ||
Host(`doobadooba.com`)"
root_url="ka-ching.com"

The reason why this is not valid is that the url does not match the rule:
so the url advertised to the unit will not in fact be routed correctly by Traefik.
Note that Traefik will still work 'correctly', i.e. the application will be
reachable at (for example) `http://doobadooba.com`.
Examples of 'good' root_url values for this case would be:

root_url="{{juju_model}}-{{juju_unit}}.foo.bar/baz"
root_url="baz.foo.bar"
root_url="doobadooba.com/choo"
type: string
Loading