Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
*~
*.pyc
**/__pycache__/
tests/.privacy-build/
tests/.review-output/
tests/.startup-review/
tests/.aggregate-review/
en
*/auto
*/build
Expand Down
102 changes: 102 additions & 0 deletions .github/workflows/privacy-candidate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Privacy candidate checks

on:
push:
paths:
- 'Docker/privacy-diagnostic/**'
- 'Docker/privacy/**'
- 'Docker/config/docassemble*.ini*'
- 'Docker/config/nginx-*.dist'
- 'Docker/nginx.conf'
- 'Docker/docassemble-supervisor.conf'
- 'Docker/docassemble-syslog-ng.conf'
- 'Docker/syslog-ng.conf'
- 'Docker/syslog-ng-docker.conf'
- 'Docker/docassemble.logrotate'
- 'Docker/restart-post-logrotate.sh'
- 'Docker/run-nginx.sh'
- 'Docker/run-uwsgi.sh'
- 'Docker/run-uwsgilog.sh'
- 'Docker/run-celery.sh'
- 'Docker/run-celery-single.sh'
- 'Docker/run-websockets.sh'
- 'Docker/run-cron.sh'
- 'Docker/cron/**'
- 'Docker/sync.sh'
- 'Docker/process-email.sh'
- 'Docker/initialize.sh'
- 'Dockerfile'
- '.dockerignore'
- 'docassemble_webapp/docassemble/webapp/log_initialize.py'
- 'docassemble_webapp/docassemble/webapp/privacy_logging.py'
- 'docassemble_webapp/docassemble/webapp/process_email.py'
- 'tests/privacy_*/**'
- 'tests/verify_privacy.sh'
- 'docs/privacy/install-catalog.json'
- '.github/workflows/privacy-candidate.yml'
pull_request:
branches: [jacob/maintained]

permissions:
contents: read

concurrency:
group: privacy-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

jobs:
populated-volume-install:
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version-file: Docker/privacy-diagnostic/go.mod
cache: false
- uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Rehearse non-mail installation and rollback on the pinned target image
run: bash tests/privacy_native/test_install_image.sh
privacy-candidate:
runs-on: ubuntu-latest
timeout-minutes: 15
env:
GOCACHE: ${{ github.workspace }}/tests/.privacy-build/go-cache
GOMODCACHE: ${{ github.workspace }}/tests/.privacy-build/go-mod
GOTMPDIR: ${{ github.workspace }}/tests/.privacy-build/go-tmp
TEST_TELEMETRY_DIR: ${{ github.workspace }}/tests/.privacy-build/telemetry
XDG_CONFIG_HOME: ${{ github.workspace }}/tests/.privacy-build/config
GOTOOLCHAIN: local
steps:
- uses: actions/checkout@v4
- name: Create Go working directories before toolchain setup
run: mkdir -p "$GOCACHE" "$GOMODCACHE" "$GOTMPDIR" "$TEST_TELEMETRY_DIR" "$XDG_CONFIG_HOME"
- uses: actions/setup-go@v5
with:
go-version-file: Docker/privacy-diagnostic/go.mod
cache: false
- uses: actions/setup-python@v5
with:
python-version: '3.14'
- name: Check diagnostics, aggregation, native lifecycle, and launchers
run: bash tests/verify_privacy.sh
- name: Build disposable native-protocol test image
run: docker build -t privacy-candidate-check -f tests/privacy_native/fixtures/privacy-check.Dockerfile tests/privacy_native/fixtures
- name: Check compiled preflight and monitor against nginx and Supervisor
run: |
bash tests/privacy_native/test_nginx_preflight_image.sh privacy-candidate-check
bash tests/privacy_native/test_supervisor_monitor_image.sh privacy-candidate-check
- name: Build pinned real uWSGI test runtime
run: docker build -t privacy-uwsgi-check -f tests/privacy_native/fixtures/uwsgi-check.Dockerfile tests/privacy_native/fixtures
- name: Check real uWSGI requests through Go capture
run: bash tests/privacy_native/test_uwsgi_image.sh privacy-uwsgi-check
- name: Build native log rotation and forwarding fixture
run: docker build -t privacy-rotation-check -f tests/privacy_native/fixtures/rotation-check.Dockerfile tests/privacy_native/fixtures
- name: Check exclusive rotation ownership and continued forwarding
run: bash tests/privacy_native/test_rotation_image.sh privacy-rotation-check
- name: Scan Go packages and reachable standard library for vulnerabilities
run: GOPROXY=https://proxy.golang.org go -C Docker/privacy-diagnostic run golang.org/x/vuln/cmd/govulncheck@v1.7.0 ./...
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ CLAUDE.md
.claude/
.claudeignore
__pycache__
tests/.privacy-build/
tests/.aggregate-review/
pyproject.toml
autoimport.py
runpylint.py
runpylint.py
6 changes: 5 additions & 1 deletion Docker/config/docassemble-expose-uwsgi.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ mount = /=docassemble.webapp.run:application
venv = /usr/share/docassemble/local3.14
pidfile = /var/run/uwsgi/uwsgi.pid
buffer-size = 32768
py-executable = /usr/share/docassemble/local3.14/bin/python
py-executable = /usr/share/docassemble/local3.14/bin/python

# Foreground request diagnostics are consumed by the privacy wrapper.
die-on-term = true
log-format = PRIVACY_REQUEST status=%(status) msecs=%(msecs)
4 changes: 4 additions & 0 deletions Docker/config/docassemble.ini.dist
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ buffer-size = 32768
touch-reload = {{DA_ROOT}}/webapp/docassemble.wsgi
py-executable = {{DA_PYTHON}}/bin/python
max-fd = 1048576

# Foreground request diagnostics are consumed by the privacy wrapper.
die-on-term = true
log-format = PRIVACY_REQUEST status=%(status) msecs=%(msecs)
4 changes: 4 additions & 0 deletions Docker/config/docassemblelog-expose-uwsgi.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ venv = /usr/share/docassemble/local3.14
module = docassemble.webapp.listlog
pidfile = /var/run/uwsgi/uwsgilog.pid
callable = app

# Foreground request diagnostics are consumed by the privacy wrapper.
die-on-term = true
log-format = PRIVACY_REQUEST status=%(status) msecs=%(msecs)
4 changes: 4 additions & 0 deletions Docker/config/docassemblelog.ini.dist
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ venv = {{DA_PYTHON}}
module = docassemble.webapp.listlog
pidfile = /var/run/uwsgi/uwsgilog.pid
callable = app

# Foreground request diagnostics are consumed by the privacy wrapper.
die-on-term = true
log-format = PRIVACY_REQUEST status=%(status) msecs=%(msecs)
14 changes: 14 additions & 0 deletions Docker/cron/docassemble-cron-daily.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#! /bin/bash

export DA_ROOT="${DA_ROOT:-/usr/share/docassemble}"
# Internal handoff only; normal invocations always enter native capture.
if [ "${1:-}" != "--privacy-captured" ]; then
exec 3>&1
exec >/dev/null 2>&1
[ -x "${DA_ROOT}/webapp/privacy-diagnostic" ] || exit 69
shopt -s execfail
exec "${DA_ROOT}/webapp/privacy-process" --component maintenance -- \
/bin/bash "${BASH_SOURCE[0]}" --privacy-captured "$@" >&3 3>&-
exec 3>&1 >/dev/null
"${DA_ROOT}/webapp/privacy-diagnostic" maintenance launch >&3 3>&-
exit $?
fi
shift

export DA_DEFAULT_LOCAL="local3.14"

export DA_ACTIVATE="${DA_PYTHON:-${DA_ROOT}/${DA_DEFAULT_LOCAL}}/bin/activate"
Expand Down
14 changes: 14 additions & 0 deletions Docker/cron/docassemble-cron-hourly.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#! /bin/bash

export DA_ROOT="${DA_ROOT:-/usr/share/docassemble}"
# Internal handoff only; normal invocations always enter native capture.
if [ "${1:-}" != "--privacy-captured" ]; then
exec 3>&1
exec >/dev/null 2>&1
[ -x "${DA_ROOT}/webapp/privacy-diagnostic" ] || exit 69
shopt -s execfail
exec "${DA_ROOT}/webapp/privacy-process" --component maintenance -- \
/bin/bash "${BASH_SOURCE[0]}" --privacy-captured "$@" >&3 3>&-
exec 3>&1 >/dev/null
"${DA_ROOT}/webapp/privacy-diagnostic" maintenance launch >&3 3>&-
exit $?
fi
shift

export DA_DEFAULT_LOCAL="local3.14"

export DA_ACTIVATE="${DA_PYTHON:-${DA_ROOT}/${DA_DEFAULT_LOCAL}}/bin/activate"
Expand Down
14 changes: 14 additions & 0 deletions Docker/cron/docassemble-cron-monthly.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#! /bin/bash

export DA_ROOT="${DA_ROOT:-/usr/share/docassemble}"
# Internal handoff only; normal invocations always enter native capture.
if [ "${1:-}" != "--privacy-captured" ]; then
exec 3>&1
exec >/dev/null 2>&1
[ -x "${DA_ROOT}/webapp/privacy-diagnostic" ] || exit 69
shopt -s execfail
exec "${DA_ROOT}/webapp/privacy-process" --component maintenance -- \
/bin/bash "${BASH_SOURCE[0]}" --privacy-captured "$@" >&3 3>&-
exec 3>&1 >/dev/null
"${DA_ROOT}/webapp/privacy-diagnostic" maintenance launch >&3 3>&-
exit $?
fi
shift

export DA_DEFAULT_LOCAL="local3.14"

export DA_ACTIVATE="${DA_PYTHON:-${DA_ROOT}/${DA_DEFAULT_LOCAL}}/bin/activate"
Expand Down
14 changes: 14 additions & 0 deletions Docker/cron/docassemble-cron-weekly.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#! /bin/bash

export DA_ROOT="${DA_ROOT:-/usr/share/docassemble}"
# Internal handoff only; normal invocations always enter native capture.
if [ "${1:-}" != "--privacy-captured" ]; then
exec 3>&1
exec >/dev/null 2>&1
[ -x "${DA_ROOT}/webapp/privacy-diagnostic" ] || exit 69
shopt -s execfail
exec "${DA_ROOT}/webapp/privacy-process" --component maintenance -- \
/bin/bash "${BASH_SOURCE[0]}" --privacy-captured "$@" >&3 3>&-
exec 3>&1 >/dev/null
"${DA_ROOT}/webapp/privacy-diagnostic" maintenance launch >&3 3>&-
exit $?
fi
shift

export DA_DEFAULT_LOCAL="local3.14"

export DA_ACTIVATE="${DA_PYTHON:-${DA_ROOT}/${DA_DEFAULT_LOCAL}}/bin/activate"
Expand Down
72 changes: 60 additions & 12 deletions Docker/docassemble-supervisor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@
loglevel=%(ENV_SUPERVISORLOGLEVEL)s
directory=/tmp

[eventlistener:privacy-monitor]
command=/usr/share/docassemble/webapp/privacy-monitor
user=www-data
events=PROCESS_STATE_EXITED,PROCESS_STATE_BACKOFF,PROCESS_STATE_FATAL,TICK_60
buffer_size=256
numprocs=1
autostart=true
autorestart=true
startsecs=1
startretries=3
priority=250
stopwaitsecs=5
stdout_logfile=NONE
redirect_stderr=false
stderr_logfile=/usr/share/docassemble/log/privacy-monitor.log
stderr_logfile_maxbytes=5MB
stderr_logfile_backups=7

[inet_http_server]
port = *:9001
username = %(ENV_DASUPERVISORUSERNAME)s
Expand Down Expand Up @@ -86,12 +104,14 @@ command=bash /usr/share/docassemble/webapp/run-celery.sh
directory=/tmp
user=www-data
numprocs=1
stdout_logfile=/usr/share/docassemble/log/worker.log
stderr_logfile=/usr/share/docassemble/log/worker.log
stdout_logfile=/usr/share/docassemble/log/privacy-celery.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=7
redirect_stderr=true
autostart=false
autorestart=true
startsecs=5
stopwaitsecs=60
stopwaitsecs=70
killasgroup=true
priority=500

Expand All @@ -100,12 +120,14 @@ command=bash /usr/share/docassemble/webapp/run-celery-single.sh
directory=/tmp
user=www-data
numprocs=1
stdout_logfile=/usr/share/docassemble/log/single_worker.log
stderr_logfile=/usr/share/docassemble/log/single_worker.log
stdout_logfile=/usr/share/docassemble/log/privacy-celerysingle.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=7
redirect_stderr=true
autostart=false
autorestart=true
startsecs=5
stopwaitsecs=60
stopwaitsecs=70
killasgroup=true
priority=500

Expand Down Expand Up @@ -145,8 +167,27 @@ killasgroup=true
stopasgroup=true
stopwaitsecs=20
priority=500
stdout_logfile=/usr/share/docassemble/log/uwsgi.log
stderr_logfile=/usr/share/docassemble/log/uwsgi.log
stdout_logfile=/usr/share/docassemble/log/privacy-uwsgi.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=7
redirect_stderr=true

[program:uwsgilog]
command=bash /usr/share/docassemble/webapp/run-uwsgilog.sh
user=www-data
autostart=false
autorestart=true
startretries=0
numprocs=1
startsecs=5
killasgroup=true
stopasgroup=true
stopwaitsecs=20
priority=500
stdout_logfile=/usr/share/docassemble/log/uwsgilog.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=7
redirect_stderr=true

[program:nginx]
command=bash /usr/share/docassemble/webapp/run-nginx.sh
Expand All @@ -159,6 +200,10 @@ killasgroup=true
stopasgroup=true
stopwaitsecs=20
priority=600
stdout_logfile=/usr/share/docassemble/log/nginx-safe.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=7
redirect_stderr=true

[program:nascent]
command=bash /usr/share/docassemble/webapp/run-nascent.sh
Expand All @@ -180,10 +225,12 @@ autorestart=true
startretries=1
startsecs=1
killasgroup=true
stopwaitsecs=20
stopwaitsecs=30
priority=600
stdout_logfile=/usr/share/docassemble/log/websockets.log
stderr_logfile=/usr/share/docassemble/log/websockets.log
stdout_logfile=/usr/share/docassemble/log/privacy-websockets.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=7
redirect_stderr=true

[program:initialize]
command=bash /usr/share/docassemble/webapp/initialize.sh
Expand All @@ -193,7 +240,7 @@ autostart=true
autorestart=false
exitcodes=0
startsecs=0
stopwaitsecs=600
stopwaitsecs=630
priority=400

[program:sync]
Expand All @@ -204,6 +251,7 @@ autorestart=false
exitcodes=0
stopasgroup=true
killasgroup=true
stopwaitsecs=40
startsecs=0
priority=600

Expand Down
8 changes: 4 additions & 4 deletions Docker/docassemble-syslog-ng.conf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
source s_docassemble {
file("/usr/share/docassemble/log/docassemble.log" flags(no-parse) follow-freq(2) program-override("docassemble") default-priority(debug));
file("/usr/share/docassemble/log/websockets.log" flags(no-parse) follow-freq(2) program-override("websockets") default-priority(debug));
file("/usr/share/docassemble/log/worker.log" flags(no-parse) follow-freq(2) program-override("celery") default-priority(debug));
file("/usr/share/docassemble/log/single_worker.log" flags(no-parse) follow-freq(2) program-override("celerysingle") default-priority(debug));
file("/usr/share/docassemble/log/uwsgi.log" flags(no-parse) follow-freq(2) program-override("uwsgi") default-priority(debug));
file("/usr/share/docassemble/log/privacy-websockets.log" flags(no-parse) follow-freq(2) program-override("websockets") default-priority(debug));
file("/usr/share/docassemble/log/privacy-celery.log" flags(no-parse) follow-freq(2) program-override("celery") default-priority(debug));
file("/usr/share/docassemble/log/privacy-celerysingle.log" flags(no-parse) follow-freq(2) program-override("celerysingle") default-priority(debug));
file("/usr/share/docassemble/log/privacy-uwsgi.log" flags(no-parse) follow-freq(2) program-override("uwsgi") default-priority(debug));
file("/var/log/apache2/access.log" flags(no-parse) follow-freq(2) program-override("apache") default-priority(debug));
file("/var/log/apache2/error.log" flags(no-parse) follow-freq(2) program-override("apache") default-priority(error));
file("/var/log/nginx/access.log" flags(no-parse) follow-freq(2) program-override("nginx") default-priority(debug));
Expand Down
Loading
Loading