Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c7c7125
Initial commit to the branch.
terjekv Aug 11, 2025
19fa8a4
Sigh.
terjekv Aug 11, 2025
9794751
Refactoring, flattning permissions for now.
terjekv Nov 12, 2025
6586313
Update towards master.
terjekv Jan 8, 2026
0f62e74
Bump version to 1.4.0
pederhan Jan 9, 2026
283e065
Add Prometheus metrics middleware and expose metrics endpoint (#605)
terjekv Jan 29, 2026
9c2e3a0
Initial commit to the branch.
terjekv Aug 11, 2025
fb00fd6
Refactoring, flattning permissions for now.
terjekv Nov 12, 2025
c09f3c6
Update towards master.
terjekv Jan 8, 2026
a7ca240
Resolve outstanding parity mismatches and return to granular permissi…
terjekv Feb 14, 2026
a501885
Batching support (optional, defaults to True).
terjekv Feb 14, 2026
db8200f
Add policy engine metrics and improve log file handling
terjekv Feb 15, 2026
da8ef02
Add tests for policy log file initialization and batch queue handling
terjekv Feb 15, 2026
48b4656
Update pyproject.toml and uv.lock against master.
terjekv Feb 15, 2026
5fdec4c
Refacgtor policy parity logging and batching functionality
terjekv Feb 15, 2026
b9b847d
Add utility methods for request normalization and middleware compatib…
terjekv Feb 15, 2026
3182191
Complete env support for treetop.
terjekv Feb 16, 2026
151688f
Documentation update.
terjekv Feb 16, 2026
7178ce2
More documentation fixes.
terjekv Feb 16, 2026
e4f4e5c
Use TreeTop policy bundles
terjekv Aug 18, 2026
1896066
Merge master and harden TreeTop bundle parity
terjekv Aug 18, 2026
47b13a8
Preserve Gunicorn PID health check
terjekv Aug 18, 2026
c362091
Update TreeTop stack and compatible CLI tests
terjekv Aug 18, 2026
e2d411c
fix: harden TreeTop policy rollout
terjekv Aug 18, 2026
6665ac2
fix: support CI Dockerfile parser
terjekv Aug 18, 2026
bb381bf
fix: run schema check from clean checkout
terjekv Aug 18, 2026
f46c238
test: restore API regression discovery
terjekv Aug 18, 2026
9b75489
test: keep contract checks image-independent
terjekv Aug 18, 2026
69190e1
ci: fetch pinned CLI revision explicitly
terjekv Aug 18, 2026
8d339f8
Add authoritative TreeTop policy mode
terjekv Aug 18, 2026
ad3260c
Refactor TreeTop authorization into request-scoped stacks
terjekv Aug 18, 2026
1454bf4
Complete synchronous TreeTop policy migration
terjekv Aug 19, 2026
2c44a8d
Make TreeTop converter importable in container tests
terjekv Aug 19, 2026
78cc307
Support TreeTop generation before package install
terjekv Aug 19, 2026
8f9a524
Generate TreeTop policy from MREG API
terjekv Aug 19, 2026
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
40 changes: 34 additions & 6 deletions .github/workflows/container-image.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
name: Container image
on:
push:
branches: [master]
tags: ['v*']
paths-ignore:
- 'ci/**'
- 'README.md'
pull_request:
types: [opened, reopened, synchronize]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

defaults:
run:
shell: bash
Expand Down Expand Up @@ -89,7 +95,10 @@ jobs:
cp -r mreg-cli/ci /tmp
C=$(cat ci/MREG-CLI_COMMIT)
cd mreg-cli
git -c advice.detachedHead=false checkout $C
# A default shallow clone can contain the commit object without all of
# its trees. Fetch the pinned revision explicitly before checkout.
git fetch --depth=1 origin "$C"
git -c advice.detachedHead=false checkout FETCH_HEAD
cp --no-clobber /tmp/ci/* ci/
- name: Run the tests
run: mreg-cli/ci/run_testsuite_and_record_V2.sh
Expand Down Expand Up @@ -130,13 +139,26 @@ jobs:
run: docker load --input mreg.tgz
- name: Start mreg
run: |
docker run --rm -t --network host --detach --name mreg \
docker run -t --network host --detach --name mreg \
-e MREG_DB_HOST=localhost -e MREG_DB_PASSWORD=mreg -e MREG_DB_USER=mreg \
mreg
- name: Wait for mreg to create the database schema and start up
run: sleep 10s
- name: Wait for mreg to become ready
run: |
for attempt in {1..30}; do
if curl --silent --show-error \
http://127.0.0.1:8000/api/meta/health/heartbeat >/dev/null; then
exit 0
fi
if [ "$(docker inspect --format '{{.State.Running}}' mreg)" != "true" ]; then
docker logs mreg
exit 1
fi
sleep 2
done
docker logs mreg
exit 1
- name: Create a user
run: docker exec -t mreg uv run /app/manage.py create_mreg_superuser --username test --password test123
run: docker exec -t mreg python /app/manage.py create_mreg_superuser --username test --password test123
- name: Authenticate using curl
shell: bash
run: |
Expand All @@ -148,10 +170,16 @@ jobs:
--write-out %{http_code} \
> /tmp/http_status_code.txt 2> /tmp/curl_errors.txt
STATUS=$(cat /tmp/http_status_code.txt)
if [ $STATUS -ge 400 ]; then
if [ "$STATUS" != "200" ]; then
cat /tmp/curl_output.txt
exit 1
fi
- name: Show mreg logs
if: always()
run: docker logs mreg
- name: Stop mreg
if: always()
run: docker rm --force mreg

publish:
name: Publish
Expand Down
40 changes: 35 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
on:
push:
branches: [master]
tags: ['v*']
paths-ignore:
- 'ci/**'
- 'README.md'
Expand All @@ -8,11 +10,43 @@ on:
types: [opened, reopened, synchronize]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

#env:
# UV_FROZEN: 1

name: CI
jobs:
treetop-bundle:
name: TreeTop bundle
runs-on: ubuntu-latest
env:
TREETOP_BUNDLE_VERSION: 0.0.5
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install treetop-bundle
run: |
curl --fail --silent --show-error --location \
--output treetop-bundle-x86_64-linux-musl.tar.gz \
"https://github.com/treetop-policy-engine/treetop-bundle/releases/download/v${TREETOP_BUNDLE_VERSION}/treetop-bundle-x86_64-linux-musl.tar.gz"
curl --fail --silent --show-error --location \
--output SHA256SUMS \
"https://github.com/treetop-policy-engine/treetop-bundle/releases/download/v${TREETOP_BUNDLE_VERSION}/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS
tar --extract --gzip --file treetop-bundle-x86_64-linux-musl.tar.gz
chmod +x treetop-bundle
- name: Validate reproducible unsigned bundle
run: scripts/check-treetop-bundle.sh
env:
TREETOP_BUNDLE_BIN: ./treetop-bundle
- name: Check generated Cedar contracts
run: python scripts/generate-treetop-schema.py --check
- name: Check generated permission policy
run: python scripts/generate-treetop-policy.py --check

test:
name: Test
runs-on: ${{ matrix.os }}
Expand All @@ -35,8 +69,6 @@ jobs:
matrix:
os: [ubuntu-latest]
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
Expand Down Expand Up @@ -68,7 +100,7 @@ jobs:
export MREG_DB_NAME=mreg MREG_DB_USER=mreg MREG_DB_PASSWORD=postgres
uv run manage.py spectacular --validate --file openapi.yml
- name: Upload OpenAPI schema
if: matrix.python-version == '3.10'
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@v7
with:
name: openapi.yml
Expand All @@ -90,8 +122,6 @@ jobs:
matrix:
os: [ubuntu-latest]
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,26 @@ mreg supports configuration via environment variables with the `MREG_` prefix. T
| `MREG_REQUESTS_THRESHOLD_VERY_SLOW` | `5000` | Very slow request threshold (ms) |
| `MREG_REQUESTS_LOG_LEVEL_VERY_SLOW` | `CRITICAL` | Log level for very slow requests |

### TreeTop Authorization

| Variable | Default | Description |
| -------- | ------- | ----------- |
| `MREG_POLICY_MODE` | `shadow` | `off`, synchronous observational `shadow`, or synchronous authoritative `enforce` |
| `MREG_POLICY_PARITY_ENABLED` | `True` | Deprecated compatibility flag used only when `MREG_POLICY_MODE` is unset |
| `MREG_POLICY_BASE_URL` | `""` | TreeTop REST base URL; an empty value disables calls |
| `MREG_POLICY_NAMESPACE` | `MREG` | Cedar namespace used for principals, actions, and resources |
| `MREG_POLICY_TIMEOUT_SECONDS` | `5.0` | TreeTop client timeout in seconds |
| `MREG_POLICY_CIRCUIT_FAILURES` | `5` | Consecutive synchronous failures that open a worker circuit |
| `MREG_POLICY_CIRCUIT_RESET_SECONDS` | `30.0` | Open-circuit cooldown |
| `MREG_POLICY_PARITY_LOG_LEVEL` | `WARNING` | Dedicated parity logger level |
| `MREG_POLICY_PARITY_LOG_DETAILS` | `False` | Include sensitive principal/resource details in parity logs |
| `MREG_POLICY_ROLLOUT_MIN_COMPARISONS` | `10000` | Minimum observations required by the enforcement gate |
| `MREG_POLICY_ROLLOUT_MAX_MISMATCH_RATE` | `0.001` | Maximum accepted mismatch ratio |
| `MREG_POLICY_ROLLOUT_MAX_ERROR_RATE` | `0.001` | Maximum accepted policy error ratio |

TreeTop bundle generation reads the three existing MREG policy endpoints with
`MREG_API_BASE_URL` and `MREG_API_TOKEN`; see [the policy documentation](docs/policies.md#bundle-source-and-build).

### Network Policy Configuration

| Variable | Default | Description |
Expand Down
1 change: 1 addition & 0 deletions ci/MREG-CLI_COMMIT
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7ace29daec005c30f33fbb14bfb9254cad1d8bc8
105 changes: 105 additions & 0 deletions docs/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,111 @@ Must be one of the following:
- `ERROR`
- `CRITICAL`

## `MREG_POLICY_PARITY_LOG_LEVEL`

Log level for the dedicated `mreg.policy.parity` logger. Default: `WARNING`

This controls parity discrepancy logs independently from `MREG_LOG_LEVEL`, so
legacy-vs-policy mismatches can be surfaced even when the general app logger is
more restrictive.

Must be one of the following:

- `DEBUG`
- `INFO`
- `WARNING`
- `ERROR`
- `CRITICAL`

## `MREG_POLICY_MODE`

Controls how MREG uses TreeTop. Default: `shadow`

- `off`: use legacy permissions and make no TreeTop calls.
- `shadow`: call TreeTop synchronously once per protected request, compare the
complete endpoint decision, and return the legacy decision.
- `enforce`: make that same synchronous endpoint decision authoritative.

`enforce` requires a non-empty `MREG_POLICY_BASE_URL`; invalid values or a
missing enforcement URL stop Django during configuration rather than silently
falling back.

## `MREG_POLICY_PARITY_ENABLED`

Deprecated compatibility flag. Default: `True`

When `MREG_POLICY_MODE` is unset, true maps to `shadow` and false maps to `off`.
An explicit mode always takes precedence.

## `MREG_POLICY_BASE_URL`

Base URL for the TreeTop policy engine REST service. Default: empty (disabled)

If unset or empty, no policy requests are made in `off`/`shadow` operation. It
is a configuration error in `enforce` mode.

Example: `http://localhost:9999`

## `MREG_POLICY_NAMESPACE`

Namespace used when constructing policy principal/action IDs. Default: `MREG`

Use Cedar-style `::` separators (commas are also accepted).

Example: `MREG` or `org::MREG`

## `MREG_POLICY_PARITY_LOG_DETAILS`

Boolean flag controlling whether parity logs include principal names, groups,
resource IDs, and resource attributes. Default: `False`

Keep this disabled unless detailed parity investigation is necessary. These
fields may contain operationally sensitive data. Parity events use the normal
console and rotating `MREG_LOG_FILE_NAME` handlers.

## `MREG_POLICY_TIMEOUT_SECONDS`

Timeout in seconds for calls to TreeTop. Default: `5.0`

Both active modes wait for the result because authorization must finish before
request processing continues. `shadow` differs only in which decision is
returned. `enforce` always fails closed on timeout, invalid response, circuit
rejection, or other TreeTop failure; there is no legacy fallback.

## Synchronous circuit breaker

- `MREG_POLICY_CIRCUIT_FAILURES` (`5`): consecutive failures before the
process-local worker circuit opens.
- `MREG_POLICY_CIRCUIT_RESET_SECONDS` (`30.0`): cooldown before one half-open
probe is allowed.

The client timeout remains `MREG_POLICY_TIMEOUT_SECONDS` (`5.0`). Each
application process owns its client and thread-safe circuit state. An open
circuit returns the legacy decision in `shadow` and denies in `enforce`.

## TreeTop enforcement rollout gates

`manage.py check_policy_rollout` evaluates Prometheus telemetry before an
operator enables policy enforcement. Defaults can be tuned with:

- `MREG_POLICY_ROLLOUT_MIN_COMPARISONS` (`10000`)
- `MREG_POLICY_ROLLOUT_MAX_MISMATCH_RATE` (`0.001`)
- `MREG_POLICY_ROLLOUT_MAX_ERROR_RATE` (`0.001`)

## TreeTop bundle generation

These variables are used only by `scripts/generate-treetop-policy.py`; they are
not Django runtime settings:

- `MREG_API_BASE_URL`: MREG base URL to read policy source data from. When
omitted, the generator uses `treetop/fixtures/policy-source.json`.
- `MREG_API_TOKEN`: API token sent to the three existing MREG endpoints. It is
required when `MREG_API_BASE_URL` is set and is never persisted.
- `MREG_API_TIMEOUT`: per-page API timeout in seconds. Default: `20`.

Use HTTPS for a remote MREG instance. The token needs authenticated read access
to labels, NetGroup regex permissions, and host-policy roles.

## `MREG_LOG_FILE_SIZE`

Maximum file size of the log file in bytes. Default: `52428800` (50MB).
Expand Down
Loading
Loading