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

Openid #10

Merged
merged 17 commits into from
Nov 3, 2024
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
51 changes: 51 additions & 0 deletions .github/workflows/cargo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Cargo CI

on:
push:
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
fmt:
name: Cargo fmt
runs-on: ubuntu-latest
strategy:
matrix:
toolchain:
- stable

steps:
- uses: actions/checkout@v4
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: rustup component add --toolchain ${{ matrix.toolchain }} rustfmt
- run: cd server && cargo fmt --all --check

build:
name: Cargo build
runs-on: ubuntu-latest
strategy:
matrix:
toolchain:
- stable
- nightly
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl

steps:
- uses: actions/checkout@v4
- name: Cache
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
server/target
key: ${{ runner.os }}-${{ matrix.toolchain }}-${{ matrix.target }}-cargo-${{ hashFiles('server/**/Cargo.lock') }}

- run: sudo apt install -y musl-tools
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: rustup target add --toolchain ${{ matrix.toolchain }} ${{ matrix.target }}
- run: cd server && cargo build --target ${{ matrix.target }}
48 changes: 48 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Release

on:
push:
tags:
- '*'

env:
CARGO_TERM_COLOR: always
DOCK_REG: registry.mrfriendly.uk

jobs:
server:
name: Server build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make build-server
- run: docker tag $DOCK_REG/wilford-server:latest $DOCK_REG/wilford-server:${{ github.ref_name }}
- run: docker push $DOCK_REG/wilford-server:latest
- run: docker push $DOCK_REG/wilford-server:${{ github.ref_name }}

ui:
name: UI build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '21'
- run: (cd ui; yarn install)

- run: make build-ui
- run: docker tag $DOCK_REG/wilford-ui:latest $DOCK_REG/wilford-ui:${{ github.ref_name }}
- run: docker push $DOCK_REG/wilford-ui:latest
- run: docker push $DOCK_REG/wilford-ui:${{ github.ref_name }}

docs:
name: Docs build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cargo install mdbook --locked

- run: make build-docs
- run: docker tag $DOCK_REG/wilford-docs:latest $DOCK_REG/wilford-docs:${{ github.ref_name }}
- run: docker push $DOCK_REG/wilford-docs:latest
- run: docker push $DOCK_REG/wilford-docs:${{ github.ref_name }}
16 changes: 11 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,17 @@ help:
echo "- upload-docs : Build and upload the docs Docker image"
echo "- upload-ui : Build and upload the ui Docker image"

test_oidc_key.pem:
openssl genrsa -out ./test_oidc_key.pem 4096

test_oidc_key.pem.pub: test_oidc_key.pem
openssl rsa -in ./test_oidc_key.pem -pubout -outform PEM -out ./test_oidc_key.pem.pub

config.json: sample_config.json
cp sample_config.json config.json

.PHONY: up
up:
up: test_oidc_key.pem test_oidc_key.pem.pub config.json
docker compose up -d
echo "Wilford UI available at http://localhost:2522"
echo "Wilford Docs available at http://localhost:2523"
Expand Down Expand Up @@ -44,7 +53,4 @@ build-docs:

.PHONY: build-ui
build-ui:
# Patch for production
sed -i "s|createWebHistory('/')|createWebHistory('/wilford')|" ui/src/router/index.ts

docker build -t registry.mrfriendly.uk/wilford-ui ui/
docker build -t registry.mrfriendly.uk/wilford-ui ui/
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ Your applications will then authenticate with Wilford,
and your users can continue using their EspoCRM login credentials.

## Development
- Copy the sample config to `config.json`
- Start all docker containers with docker-compose:
```
docker compose up -d
- Start everything with
```bash
make up
```
This will:
- Create an OIDC signing key if it doesn't exist
- Copy `sample_config.json` to `config.json`
- Start all containers

The following services will be available:
- The backend, on port [2521](http://localhost:2512)
Expand All @@ -32,7 +35,20 @@ After starting, you should configure an API-client in EspoCRM:
10. Select the role you just created under `Roles`
11. Set `Authentication method` to `HMAC` and select `Save`
12. Copy the `API Key` and `Secret Key` to `config.json`
13. Hit Ctrl+C and run `docker compose up` again.
13. Restart Wilford
```bash
docker-compose down
make up
```

## Generate OIDC Key
```bash
# Private key
openssl genrsa -out ./oidc.pem 4096

# Public key
openssl rsa -in ./oidc.pem -pubout -outform PEM -out ./oidc.pem.pub
```

# License
MIT or Apache-2.0, at your option
13 changes: 12 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ services:
context: server
dockerfile: Dockerfile
ports:
- "2521:8080"
- "2521:2521"
environment:
- "CONFIG_PATH=/config.json"
- "RUST_LOG=DEBUG"
volumes:
- "./config.json:/config.json"
- "./test_oidc_key.pem:/test_oidc_key.pem"
- "./test_oidc_key.pem.pub:/test_oidc_key.pem.pub"
depends_on:
- "mariadb-wilford"

Expand Down Expand Up @@ -63,3 +66,11 @@ services:
- "./tmp/espocrm:/var/www/html"
depends_on:
- mariadb-espocrm

nginx:
image: nginx
network_mode: "host"
volumes:
- "./localhost.pem:/etc/ssl/certs/ssl-cert-snakeoil.pem"
- "./localhost-key.pem:/etc/ssl/private/ssl-cert-snakeoil.key"
- "./nginx.conf:/etc/nginx/conf.d/default.conf:ro"
3 changes: 3 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Summary
- [Introduction](introduction.md)
- [Deploying](./deploy/index.md)
- [Configuration](./deploy/configuration.md)
- [OAuth2 Proxy](./deploy/oauth2_proxy.md)
- [OAuth2](oauth2/index.md)
- [Authorization](oauth2/authorization.md)
- [API](api/index.md)
Expand Down
1 change: 0 additions & 1 deletion docs/src/api/clients/internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ This endpoint provides information about the OAuth2 client
{
"name": "<name of the client>",
"client_id": "<OAuth2 client_id>",
"client_secret": "<OAuth2 client_secret>",
"redirect_uri": "<OAuth2 redirect_uri>"
}
```
2 changes: 1 addition & 1 deletion docs/src/api/user/index.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# User
User info & user managment
User info & user management
19 changes: 19 additions & 0 deletions docs/src/deploy/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Configuration


## Default config file
```json
{{#include ../../../sample_config.json}}
```

## Environmental variables
```
CONFIG_PATH=<path to config.json>
```

## Available options
The following Rust structs define the layout of the configuration.
An example of how this translates to JSON can be found in the [sample config](#default-config-file)
```rust,noplayground
{{#include ../../../server/wilford/src/config.rs:config}}
```
1 change: 1 addition & 0 deletions docs/src/deploy/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Deployment Documentation
96 changes: 96 additions & 0 deletions docs/src/deploy/oauth2_proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# OAuth2 Proxy

Wilford supports running with [oauth2-proxy](https://oauth2-proxy.github.io/oauth2-proxy/).
Using oaut2-proxy together with Wilford and nginx, you can protect static resources without needing to modify them.

## OAuth2 Config
Sample docker-compose file for running oauth2-proxy.
Replace the `CLIENT_ID` and `CLIENT_SECRET` with the ID and Secret generated by Wilford. Use `REDIRECT_URL` as the Redirect URL in Wilford.
The `COOKIE_SECRET` should be a securely generated random string.
```yml
version: '3.2'
services:
oauth2_proxy:
image: quay.io/oauth2-proxy/oauth2-proxy
environment:
- "OAUTH2_PROXY_COOKIE_SECRET=VsZqXqHQzwdPUcEUDgNxmQvTRZ46DtlQr8q-HtomkL8="
- "OAUTH2_PROXY_COOKIE_SECURE=true"
- "OAUTH2_PROXY_COOKIE_DOMAIN=localhost"
- "OAUTH2_PROXY_CLIENT_ID=NuWrxroZbOuhBL2ufHx9zj0qKT6XXQRg"
- "OAUTH2_PROXY_CLIENT_SECRET=vwn0MqNbD9qAnvCbGns9sNtikWC7eTM2V7DIz85vcimtxm12"
- "OAUTH2_PROXY_OIDC_ISSUER_URL=https://localhost:8443"
- "OAUTH2_PROXY_REDIRECT_URL=https://localhost:8443/oauth2/callback"
- "OAUTH2_PROXY_PROVIDER=oidc"
- "OAUTH2_PROXY_EMAIL_DOMAINS=*"
- "OAUTH2_PROXY_OIDC_EMAIL_CLAIM=sub_email"
- "OAUTH2_PROXY_PROVIDER_DISPLAY_NAME=Koala"
- "OAUTH2_PROXY_CUSTOM_SIGN_IN_LOGO=-"
- "OAUTH2_PROXY_BANNER=<img src='https://public.svsticky.nl/logos/logo_outline_kleur.png'/>"
- "OAUTH2_PROXY_FOOTER=-"
network_mode: "host"
```

## Nginx auth_directive
Using this setup, you can use the nginx auth directive very easily:
```conf
location /secure {
auth_request /oauth2/auth;
error_page 401 =403 /oauth2/sign_in;
proxy_pass http://my-secure-backend;
}
```

## Localhost
The JWKS specification requires it be served over https. When working locally, this can be a bit of a pain.

### Generate certificates for localhost
Install the required tools:
```bash
sudo apt install -y libnss3-tools mkcert
```
Generate a CA cert:
```bash
mkcert --install
```

Generate SSL certificate for `localhost`, from the repository root:
```bash
mkcert localhost
```

### Oauth2-proxy
Add the following to the docker-compose file:
```yml
volumes:
- "/usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro"
- "/etc/ssl/certs:/etc/ssl/certs:ro"
```

### nginx
Use the following block for Wilford:
```conf
server {
listen 8443 ssl default_server;
server_name _;

ssl_certificate /etc/ssl/certs/ssl-cert-localhost.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-localhost.key;

location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:2521;
}
}
```
docker-compose:
```yml
nginx:
image: nginx
network_mode: "host"
volumes:
- "./localhost.pem:/etc/ssl/certs/ssl-cert-localhost.pem"
- "./localhost-key.pem:/etc/ssl/private/ssl-cert-localhost.key"
- "./nginx.conf:/etc/nginx/conf.d/default.conf:ro"
```
10 changes: 8 additions & 2 deletions docs/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
Wilford is a OAuth2 Provider using EspoCRM as its credentials provider.

## Sources
Wilford's implementation of OAuth2 is derived from the following documents:
Wilford's implementation of OAuth2 and OpenID Connect is derived from the following documents:
- [RFC6749](https://datatracker.ietf.org/doc/html/rfc6749)
- [RFC6750](https://datatracker.ietf.org/doc/html/rfc6750)
- [RFC7662](https://datatracker.ietf.org/doc/html/rfc7662)
- [RFC7662](https://datatracker.ietf.org/doc/html/rfc7662)
- [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html)

## TODO
Not everything is implemented 100%. I'd like to add support for:
- [A.4](https://openid.net/specs/openid-connect-core-1_0.html#code-id_tokenExample) (`response_type=code id_token`).
At the moment only `response_type=id_token token` is supported.
Loading
Loading