Skip to content

Commit

Permalink
feat: setup docker build + running
Browse files Browse the repository at this point in the history
  • Loading branch information
tymees committed Sep 2, 2024
1 parent 8ad63a6 commit c3405f6
Show file tree
Hide file tree
Showing 17 changed files with 430 additions and 242 deletions.
44 changes: 44 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# App specific
certificates
*.sqlite3
docker_initial_setup.sh

# Common
README.md

# Docker
docker-compose.yml
Dockerfile
.docker
.dockerignore
container.env

# git
.git
.gitattributes
.gitignore
# GitHub
.github

## Python
# Byte-compiled
**/__pycache__/
**/*.py[cod]

# Virtual environment
.env
.venv/
venv/

## Editors
# Vim swap files
**/*.swp

# VS Code
.vscode/

# JetBrains
.idea

# Notepad++
.editorconfig
17 changes: 17 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true

[*]
end_of_line = lf
indent_style = space
indent_size = 4
max_line_length = 80
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true

[*.py]
max_line_length = 88
46 changes: 46 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Build and Push Docker Images

on:
push:
tags:
- '*'
workflow_dispatch:

env:
IMAGE_NAME: humitifier
DOCKERFILE_PATH: ./Dockerfile

jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push main image
uses: docker/build-push-action@v4
with:
context: .
file: ${{ env.DOCKERFILE_PATH }}
push: true
tags: |
ghcr.io/centrefordigitalhumanities/development-idp/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
- name: Grype Scan
id: scan
uses: anchore/scan-action@v3
with:
image: ghcr.io/centrefordigitalhumanities/humitifier/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
fail-build: false

- name: upload Grype SARIF report
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
26 changes: 26 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM python:3.11-alpine3.20

ENV PYTHONUNBUFFERED=1
# Copy app
WORKDIR /app
COPY . /app

# Install dependencies
RUN apk add git xmlsec gettext
RUN pip install -r requirements.txt
RUN pip install gunicorn

# Cleanup
RUN apk del git

# Compile messages
RUN python manage.py compilemessages

# Collect static files
## Create public dir to store them in
RUN mkdir -p /app/public/static
## Collect them
RUN python manage.py collectstatic --noinput

EXPOSE 7000
CMD ["sh", "docker/run.sh"]
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

A quick and dirty IdP for local development with applications using Federated Authentication.

Internally it's follows SurfConext attribute/claim naming, but has built-in
Internally it's follows SurfConext attribute/claim naming, but has built-in
profiles to act like the UU IdP.

NOTE: Currently only SAML is implemented, with OpenID possibly being added in
NOTE: Currently only SAML is implemented, with OpenID possibly being added in
the future.

## Instructions

### Running with Docker

TODO: write this. TL;DR: ``docker-compose up`` and `./docker_initial_setup.sh` the first time.

### Running locally

1. Setup a virtualenv and activate it
2. Install dependencies ``pip install -r requirements.txt``
4. Run migrations ``python manage.py migrate``
Expand All @@ -18,8 +24,8 @@ the future.
* This will create an admin user with username/pass: admin/admin. Will override any existing user with pk 1
* Otherwise, create an admin user using ``python manage.py createsuperuser``
7. (Optional) Load test users ``python manage.py loaddata main/fixtures/surfconext-test-users.json``
* These test users are identical to the test users in SurfConext's test environment.
* These accounts will override any existing user using a PK between 2 and 40.
* These test users are identical to the test users in SurfConext's test environment.
* These accounts will override any existing user using a PK between 2 and 40.
8. Verify that ``BASE_URL`` in ``testidp/saml_settings.py`` is set to the correct host for your usage
* By default this is ``localhost:7000``, which is probably fine?
9. Run the IDP ``python manage.py runserver <port>``
Expand All @@ -28,14 +34,14 @@ the future.

## Adding SAML Service Providers

1. Make sure your app has SAML already setup and is using
1. Make sure your app has SAML already setup and is using
``http(s)://localhost:7000/saml/idp/metadata`` as it's IdP
* Replacing ``localhost:7000`` with the actual IP of the IdP
2. Click 'New' next to Service Provider in the app
3. Provide at least your SP's ``entity_id`` and ``metadata`` (preferably by URL import)
4. Choose your starting attribute map*
4. Choose your starting attribute map*
5. Done!
6. Optionally: review your new SP by editting. You might want to add missing
6. Optionally: review your new SP by editting. You might want to add missing
attributes to the attribute map

### Note on attribute maps
Expand All @@ -44,13 +50,13 @@ In SAML, (well, PySAML), the term attribute map is often used and often not even
referring to the same thing. This can be confusing, so to clear up:

In the context _of this app_ you'll only have to worry about SP attribute maps,
which both maps the attribute name (as stored in the dev-IdP's database) to the
which both maps the attribute name (as stored in the dev-IdP's database) to the
name sent to the SP and restricts what attribute names are sent. (Any attribute
not in the dict will not be sent back to the SP.)

For example, internally the Solis-ID is named ``username``, but the UU IdP calls
this attribute ``uuShortId``. Thus, we need to _map_ ``username`` to
``uuShortId``.
this attribute ``uuShortId``. Thus, we need to _map_ ``username`` to
``uuShortId``.

Thus, you'll get this attribute map:
```json
Expand All @@ -59,7 +65,7 @@ Thus, you'll get this attribute map:
}
```

However, with this map the IdP will only supply the SP the solis-id of the
However, with this map the IdP will only supply the SP the solis-id of the
logged-in user. Thus, a more common attribute map would be:

```json
Expand All @@ -71,16 +77,16 @@ logged-in user. Thus, a more common attribute map would be:
}
```

The app provides a couple preset attribute maps, which can be chosen when
The app provides a couple preset attribute maps, which can be chosen when
registering an SP in the app. These maps can also be consulted in the file
`main/attribute_map_presets.py`.

## Known Issues
### xmlsec1 bug for Mac users
If you are working on an Apple device, you might run into problems with reading
the certificates for some obscure mac reasons. The currently functioning
If you are working on an Apple device, you might run into problems with reading
the certificates for some obscure mac reasons. The currently functioning
workaround (as per 10-1-2024) is reverting your `xmlsec1` package to version
`1.2.37`. You can do that with the following code ([source](https://github.com/xmlsec/python-xmlsec/issues/254#issuecomment-1726249435>`)):
`1.2.37`. You can do that with the following code ([source](https://github.com/xmlsec/python-xmlsec/issues/254#issuecomment-1726249435>`)):

```shell
brew uninstall libxmlsec1
Expand Down
12 changes: 12 additions & 0 deletions container.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
DJANGO_SECRET_KEY="django-insecure-lb=q@u4df-x0th(5u%$eye_ti#etst+5z+%2=lrh$$le3&v_y$"
DJANGO_DEBUG="True"
DJANGO_DEBUG_TOOLBAR="True"
DJANGO_HOST="localhost:7000"
DJANGO_ALLOWED_HOSTS="localhost,127.0.0.1"
DJANGO_DB_TYPE="sqlite3"
DJANGO_SQLLITE_FILE="/run/db/db.sqlite3"
DJANGO_HTTPS="False"

DJANGO_IDP_PRIVATE_KEY="/run/secrets/private_key"
DJANGO_IDP_PUBLIC_CERT="/run/secrets/public_cert"
# TODO: document all variables _somewhere_
109 changes: 0 additions & 109 deletions convertcsv.py

This file was deleted.

Empty file added db/.empty
Empty file.
28 changes: 28 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
services:
dev-idp:
build: .
ports:
- 7000:7000
env_file:
- ./container.env
volumes:
- ./db:/run/db
networks:
- default
# Below allows for debugging with pdb etc.
stdin_open: true
tty: true
secrets:
- private_key
- public_cert


networks:
default:

secrets:
private_key:
file: ./certificates/private.key
public_cert:
file: ./certificates/public.cert

7 changes: 7 additions & 0 deletions docker/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

# Migrate the database
python manage.py migrate

# Run da server
exec gunicorn testidp.wsgi:application -c gunicorn.conf.py "$@"
Loading

0 comments on commit c3405f6

Please sign in to comment.