Skip to content

Commit 2542d7b

Browse files
authored
3.10.2 (#12)
* - prepare for 3.11 release - added healthz check - added 503 custom loading page * - remove of bash code - removed entrypoint.sh - using privacyidea functions for config and setup - preparing for 3.11 - update documentation - added configuration variables - re-write pi.cfg * - prepare new 3.10.2 * 3.10.2 release with new entrypoint.py
1 parent 801f046 commit 2542d7b

File tree

15 files changed

+213
-129
lines changed

15 files changed

+213
-129
lines changed

.github/workflows/docker-publish.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
name: Docker
22

33
on:
4-
release:
5-
types: [prereleased,released]
4+
push:
5+
# Sequence of patterns matched against refs/tags
6+
tags:
7+
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
8+
69
env:
710
# Use docker.io for Docker Hub if empty
811
REGISTRY: ghcr.io
@@ -64,7 +67,9 @@ jobs:
6467
push: ${{ github.event_name != 'pull_request' }}
6568
tags: ${{ steps.meta.outputs.tags }}
6669
labels: ${{ steps.meta.outputs.labels }}
67-
build-args: PI_VERSION=${{ github.ref_name }}
70+
build-args: |
71+
- PI_VERSION=${{ github.ref_name }}
72+
- PI_VERSION_BUILD=${{ github.ref_name }}
6873
6974
7075
- name: Sign the published Docker image

Changelog

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Version 3.10.2, 2025-01-30
2+
3+
Enhancements:
4+
* Removed bash scripting including shaky logic
5+
* NGINX Template including landing site if container is not ready yet
6+
* More values for pi.cfg
7+
* Removed unecessary binds
8+
* New persistent logic, file location inside container (app, configuration,...)
9+
10+
Changed:
11+
* Using entrypoint.py instead of bash script
12+
* Using privacyIDEA application context calls for entrypoint.py (create_db...)
13+
14+
Fixes:
15+
* Fix some minor problems
16+

Dockerfile

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,62 @@
1+
### Build privacyidea container including gssapi (Kerberos) and hsm
2+
13
### build stage
24
###
35
FROM cgr.dev/chainguard/wolfi-base AS builder
46

57
ARG PYVERSION=3.12
6-
ARG PI=3.10.1
7-
ARG PI_REQUIREMENTS=3.10.1
8+
ARG PI_VERSION=3.10.2
9+
ARG PI_REQUIREMENTS=3.10.2
810
ARG GUNICORN==23.0.0
9-
ARG PSYCOPG2==2.9.9
11+
ARG PSYCOPG2==2.9.10
12+
ARG PYKCS11==1.5.14
13+
1014
ENV LANG=C.UTF-8
1115
ENV PYTHONDONTWRITEBYTECODE=1
1216
ENV PYTHONUNBUFFERED=1
1317
ENV PATH="/privacyidea/venv/bin:$PATH"
1418

1519
WORKDIR /privacyidea
16-
RUN apk add python-${PYVERSION} py${PYVERSION}-pip && \
20+
RUN apk add python-${PYVERSION} py${PYVERSION}-pip python3-dev && \
21+
#RUN apk add python-${PYVERSION} py${PYVERSION}-pip python3-dev build-base krb5-conf krb5-dev swig && \
1722
chown -R nonroot:nonroot /privacyidea/
1823

1924
USER nonroot
2025
RUN python -m venv /privacyidea/venv
2126
RUN pip install -r https://raw.githubusercontent.com/privacyidea/privacyidea/v${PI_REQUIREMENTS}/requirements.txt
22-
RUN pip install psycopg2-binary==${PSYCOPG2} privacyidea==${PI} gunicorn==${GUNICORN}
27+
RUN pip install psycopg2-binary==${PSYCOPG2} privacyidea==${PI_VERSION} gunicorn==${GUNICORN}
28+
#RUN pip install -r https://raw.githubusercontent.com/privacyidea/privacyidea/v${PI_REQUIREMENTS}/requirements-kerberos.txt
29+
# Workaroud for https://github.com/privacyidea/privacyidea/issues/4127
30+
#RUN pip install -r https://raw.githubusercontent.com/privacyidea/privacyidea/v${PI_REQUIREMENTS}/requirements-hsm.txt
31+
#RUN pip install pykcs11==${PYKCS11}
2332

2433
ADD https://raw.githubusercontent.com/privacyidea/privacyidea/v${PI_REQUIREMENTS}/deploy/privacyidea/NetKnights.pem /privacyidea/etc/persistent/
2534

2635
COPY conf/pi.cfg /privacyidea/etc/
2736
COPY conf/logging.cfg /privacyidea/etc/
28-
COPY templates/healthcheck.py /privacyidea/venv/bin/healthcheck.py
29-
COPY entrypoint.sh /privacyidea/venv/bin/entrypoint.sh
37+
COPY entrypoint.py /privacyidea/entrypoint.py
3038

3139
### final stage
3240
###
3341
FROM cgr.dev/chainguard/wolfi-base
3442

35-
ARG version=3.12
43+
ARG PYVERSION=3.12
3644
ENV PYTHONUNBUFFERED=1
3745
ENV PATH="/privacyidea/venv/bin:/privacyidea/bin:$PATH"
3846
ENV PRIVACYIDEA_CONFIGFILE="/privacyidea/etc/pi.cfg"
3947
LABEL maintainer="Marco Moenig <[email protected]>"
40-
LABEL org.opencontainers.image.source=https://github.com/gpappsoft/privacyidea-docker.git
41-
LABEL org.opencontainers.image.url=https://github.com/gpappsoft/privacyidea-docker.git
48+
LABEL org.opencontainers.image.source="https://github.com/gpappsoft/privacyidea-docker.git"
49+
LABEL org.opencontainers.image.url="https://github.com/gpappsoft/privacyidea-docker.git"
50+
LABEL org.opencontainers.image.description="Simply deploy and run a privacyIDEA instance in a container environment."
4251

4352
WORKDIR /privacyidea
4453
VOLUME /privacyidea/etc/persistent
4554

46-
RUN apk add python-${version}
47-
#&& \ chown -R nonroot:nonroot /privacyidea/
55+
RUN apk add python-${PYVERSION}
4856

49-
COPY --from=builder /privacyidea/ /privacyidea
57+
COPY --from=builder /privacyidea/ /privacyidea
5058

51-
EXPOSE ${PORT}
59+
EXPOSE ${PI_PORT}
5260

5361
# Run privacyIDEA-Server
54-
ENTRYPOINT [ "entrypoint.sh" ]
62+
ENTRYPOINT [ "python", "/privacyidea/entrypoint.py" ]

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
PI_VERSION := 3.10.1
2-
PI_VERSION_BUILD := 3.10.1
1+
PI_VERSION := 3.10.2
2+
PI_VERSION_BUILD := 3.10.2
33
IMAGE_NAME := privacyidea-docker:${PI_VERSION}
44

55
BUILDER := docker build
@@ -18,7 +18,7 @@ TAG := prod
1818
PROFILE := stack
1919

2020
build:
21-
${BUILDER} --no-cache -t ${IMAGE_NAME} --build-arg PI_VERSION_BUILD=${PI_VERSION_BUILD} --build-arg PI_VERSION=${PI_VERSION} .
21+
${BUILDER} --no-cache -t ${IMAGE_NAME} --build-arg PI_VERSION_BUILD=${PI_VERSION_BUILD} --build-arg PI_VERSION=${PI_VERSION} .
2222

2323
push:
2424
${CONTAINER_ENGINE} tag ${IMAGE_NAME} ${REGISTRY}/${IMAGE_NAME}

README.md

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55

66
Simply deploy and run a privacyIDEA instance in a container environment.
77

8-
> [!Important]
9-
> #### The base-image changed from ``python-slim`` to [Wolfi OS](https://github.com/wolfi-dev).
10-
> The old approach is still available in the ```python-slim``` Branch.
11-
128
## Overview
139
[privacyIDEA](https://github.com/privacyidea/privacyidea) is an open solution for strong two-factor authentication like OTP tokens, SMS, smartphones or SSH keys.
1410

@@ -44,8 +40,6 @@ make cert fullstack
4440
```
4541
Username / password: admin / admin
4642

47-
**Starting the container for the first time could take a few seconds. Please reload the page after 20-30 seconds, if you get a 502 error from the reverse proxy.**
48-
4943
## Repository
5044

5145
| Directory | Description |
@@ -65,7 +59,7 @@ Sample images from this project can be found here:
6559
| [ghcr.io](https://github.com/gpappsoft/privacyidea-docker/pkgs/container/privacyidea-docker)| ```docker pull ghcr.io/gpappsoft/privacyidea-docker:latest```|
6660

6761
> [!Note]
68-
> ```latest``` tagged image is maybe a pre- or development-release. Please use always a release number (like ```3.10.1```)
62+
> ```latest``` tagged image is maybe a pre- or development-release. Please use always a release number (like ```3.11```)
6963
7064
## Quickstart
7165

@@ -118,7 +112,7 @@ You can use *Makefile* targets to build different images with different privacyI
118112

119113
#### Build a specific privacyIDEA version
120114
```
121-
make build PI_VERSION=3.10.1
115+
make build PI_VERSION=3.11 PI_VERSION_BUILD=3.11
122116
```
123117

124118
#### Push to a registry
@@ -145,7 +139,7 @@ make distclean
145139

146140
| target | optional ARGS | description | example
147141
---------|----------|---|---------
148-
| ```build ``` | ```PI_VERSION```<br> ```IMAGE_NAME```|Build an image. Optional: specify the version and image name| ```make build PI_VERSION=3.10```|
142+
| ```build ``` | ```PI_VERSION```<br> ```IMAGE_NAME```|Build an image. Optional: specify the version, requirements version and image name| ```make build PI_VERSION=3.11 PI_VERSION_BUILD=3.11```|
149143
| ```push``` | ```REGISTRY```|Tag and push the image to the registry. Optional: specify the registry URI. Defaults to *localhost:5000*| ```make push REGISTRY=docker.io/gpappsoft/privacyidea-docker```|
150144
| ```run``` | ```PORT``` <br> ```TAG``` |Run a standalone container with gunicorn and sqlite. Optional: specify the prefix tag of the container name and listen port. Defaults to *pi* and port *8080*| ```make run TAG=prod PORT=8888```|
151145
| ```secret``` | |Generate secrets to use in an environment file | ```make secret```|
@@ -269,7 +263,7 @@ You can start the stack in the background with console detached using the **-d**
269263

270264
Full example including build with ```make```targets:
271265
```
272-
make cert build push stack PI_VERSION=3.10 TAG=pidev
266+
make cert build push stack PI_VERSION=3.11 PI_VERSION_BUILD=3.11 TAG=pidev
273267
```
274268
---
275269
Now you can deploy additional containers like OpenLDAP for user realms or Owncloud as a client to test 2FA authentication.
@@ -300,6 +294,7 @@ Have fun!
300294
```SUPERUSER_REALM```|"admin,helpdesk"| Admin realms, which can be used for policies in privacyIDEA. Comma separated list. See the privacyIDEA documentation for more information.
301295
```PI_SQLALCHEMY_ENGINE_OPTIONS```| False | Set pool_pre_ping option. Set to ```True``` for DB clusters (like Galera).
302296

297+
**Additional enviornment variables** starting with ```PI_``` will automatically added to ```pi.cfg```
303298

304299
### DB connection parameters
305300
| Variable | Description

conf/pi.cfg

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,31 @@
11
import logging
22
import os
3-
4-
# The realm, where users are allowed to login as administrators
5-
SUPERUSER_REALM = os.getenv("SUPERUSER_REALM","admin,helpdesk").split(',')
6-
7-
# Your database
8-
SQLALCHEMY_DATABASE_URI = os.getenv("DB_API") + "://" + os.getenv("DB_USER") + ":" + os.getenv("DB_PASSWORD") + "@" + os.getenv("DB_HOST") + ":" + os.getenv("DB_PORT") + "/" + os.getenv("DB_NAME") + os.getenv("DB_EXTRA_PARAMS") if (os.getenv("DB_PASSWORD")) else "sqlite:////privacyidea/etc/persistent/data.sqlite"
9-
10-
# This is used to encrypt the auth_token
11-
SECRET_KEY = open('%s' % os.getenv("PI_SECRET")).read().rstrip('\n') if os.path.exists(os.getenv("PI_SECRET")) else os.getenv("PI_SECRET")
12-
13-
# This is used to encrypt the admin passwords
14-
PI_PEPPER = open('%s' % os.getenv("PI_PEPPER")).read().rstrip('\n') if os.path.exists(os.getenv("PI_PEPPER")) else os.getenv("PI_PEPPER")
15-
# This is used to encrypt the token data and token passwords
16-
PI_ENCFILE = '/privacyidea/etc/persistent/enckey'
17-
18-
# Scripts
19-
PI_SCRIPT_HANDLER_DIRECTORY='/privacyidea/scripts'
20-
21-
# This is used to sign the audit log
22-
PI_AUDIT_KEY_PRIVATE = '/privacyidea/etc/persistent/private.pem'
23-
PI_AUDIT_KEY_PUBLIC = '/privacyidea/etc/persistent/public.pem'
24-
PI_AUDIT_SQL_TRUNCATE = True
25-
26-
# The Class for managing the SQL connection pool
27-
PI_ENGINE_REGISTRY_CLASS = os.getenv("PI_REGISTRY_CLASS", "shared")
28-
PI_AUDIT_POOL_SIZE = 20
29-
30-
# Logging
31-
PI_LOGCONFIG = '/privacyidea/etc/logging.cfg'
32-
PI_LOGLEVEL = logging.getLevelName(os.getenv("PI_LOGLEVEL", "INFO").upper())
33-
PI_UUID_FILE = '/privacyidea/etc/persistent/uuid.txt'
34-
# Use true if DB cLuster used (e.g. galera, oracle...)
35-
SQLALCHEMY_ENGINE_OPTIONS= {"pool_pre_ping": os.getenv("PI_SQLALCHEMY_ENGINE_OPTIONS", "False")}
3+
import pprint
4+
5+
pi_os_special_vars = {
6+
'SUPERUSER_REALM': os.getenv("SUPERUSER_REALM","admin,helpdesk").split(','),
7+
'PI_ENCFILE' : '/privacyidea/etc/persistent/enckey',
8+
'PI_SCRIPT_HANDLER_DIRECTORY' : '/privacyidea/scripts',
9+
'PI_AUDIT_KEY_PRIVATE' : '/privacyidea/etc/persistent/private.pem',
10+
'PI_AUDIT_KEY_PUBLIC' : '/privacyidea/etc/persistent/public.pem',
11+
'PI_AUDIT_SQL_TRUNCATE' : os.getenv("PI_AUDIT_SQL_TRUNCATE",True),
12+
'PI_ENGINE_REGISTRY_CLASS': os.getenv("PI_REGISTRY_CLASS", "shared"),
13+
'PI_AUDIT_POOL_SIZE' : os.getenv("PI_AUDIT_POOL_SIZE", "20"),
14+
'PI_AUDIT_NO_SIGN' : os.getenv("PI_AUDIT_POOL_SIZE", False),
15+
'PI_LOGCONFIG' : '/privacyidea/etc/logging.cfg',
16+
'PI_LOGLEVEL' : logging.getLevelName(os.getenv("PI_LOGLEVEL", "INFO").upper()),
17+
'PI_UUID_FILE' : '/privacyidea/etc/persistent/uuid.txt',
18+
'PI_SQLALCHEMY_ENGINE_OPTIONS' : {"pool_pre_ping": os.getenv("PI_SQLALCHEMY_ENGINE_OPTIONS", "False")} ,
19+
'SQLALCHEMY_DATABASE_URI' : os.getenv("DB_API",'sqlite:////privacyidea/etc/persistent/data.sqlite') + "://" + os.getenv("DB_USER",'') + ":" + os.getenv("DB_PASSWORD",'') + "@" + os.getenv("DB_HOST",'') + ":" + os.getenv("DB_PORT",'') + "/" + os.getenv("DB_NAME",'') + os.getenv("DB_EXTRA_PARAMS",'')
20+
}
21+
22+
pi_os_vars = {key: value for key, value in os.environ.items() if key.startswith('PI_')}
23+
24+
for k, v in pi_os_vars.items():
25+
locals()[k] = v
26+
27+
for k, v in pi_os_special_vars.items():
28+
locals()[k] = v
29+
30+
#debugenv = locals().copy()
31+
#pprint.pprint (debugenv)

docker-compose.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ services:
8181
source: ./templates/nginx_default.conf.template
8282
target: /etc/nginx/templates/default.conf.template
8383
read_only: true
84+
- type: bind
85+
source: ./templates/502.html
86+
target: /etc/privacyidea/customization/502.html
87+
read_only: true
8488
networks:
8589
- privacyidea
8690
restart: always

entrypoint.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import os
2+
import base64
3+
from time import sleep
4+
from privacyidea.app import create_app
5+
from privacyidea.cli.pimanage.pi_setup import (create_enckey, create_audit_keys,create_pgp_keys)
6+
from privacyidea.lib.auth import create_db_admin
7+
from privacyidea.models import db
8+
9+
10+
app = create_app(config_name='production',config_file='/privacyidea/etc/pi.cfg')
11+
12+
os.chdir('/privacyidea/venv/lib/python3.12/site-packages/privacyidea')
13+
14+
# Update database schema, if set
15+
PI_UPDATE = os.environ.get('PI_UPDATE', False)
16+
17+
# Create enckey
18+
if not os.path.exists('/privacyidea/etc/persistent/enckey') or os.path.getsize('/privacyidea/etc/persistent/enckey') == 0:
19+
print("### Create enckey ###")
20+
if 'PI_ENCKEY' in os.environ and not os.path.exists('/privacyidea/etc/persistent/enckey'):
21+
print("### Use PI_ENCKEY ###")
22+
with open('/privacyidea/etc/persistent/enckey', 'wb') as f:
23+
f.write(base64.b64decode(os.environ['PI_ENCKEY']))
24+
os.chmod('/privacyidea/etc/persistent/enckey', 0o400)
25+
else:
26+
print("### Use create_enckey() ###")
27+
with app.app_context():
28+
create_enckey()
29+
30+
# Create audit keys if not exists
31+
if not os.path.exists('/privacyidea/etc/persistent/private.pem'):
32+
print("### Create audit and pgp keys ###")
33+
with app.app_context():
34+
create_audit_keys()
35+
create_pgp_keys()
36+
37+
# Bootstrap database
38+
if os.path.exists('/privacyidea/etc/persistent/enckey') and not os.path.exists('/privacyidea/etc/persistent/dbcreated'):
39+
print("### Creating database tables ###")
40+
with app.app_context():
41+
dbcreate = db.create_all()
42+
open('/privacyidea/etc/persistent/dbcreated', 'w').close()
43+
44+
print("### Create initial admin user ###")
45+
with app.app_context():
46+
create_db_admin(os.environ.get('PI_ADMIN', 'admin'), 'email',os.environ.get('PI_ADMIN_PASS', 'admin'))
47+
48+
# Run the app using gunicorn WSGI HTTP server
49+
cmd = [ "python",
50+
"-m", "gunicorn",
51+
"-w", "1",
52+
"-b", os.environ['PI_ADDRESS']+":"+os.environ['PI_PORT'],
53+
"privacyidea.app:create_app(config_name='production',config_file='/privacyidea/etc/pi.cfg')"
54+
]
55+
56+
os.execvp('python', cmd)

entrypoint.sh

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)