Skip to content
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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ tests
**/__pycache__
**/.terraform
**/terraform.tfstate*
src/scm_decrypt_bypass/terraform/tests
src/panos_decrypt_bypass/terraform/tests
18 changes: 14 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# scm-decrypt-bypass settings. Copy to .env and fill in. Never commit .env.
# panos-decrypt-bypass settings. Copy to .env and fill in. Never commit .env.
# Every variable is described in docs/configuration.md.

# --- Web GUI login (required) --------------------------------------------------
Expand All @@ -8,7 +8,13 @@ WEBGUI_PASSWORD=
# WEBGUI_AUTH=password
# WEBGUI_SESSION_HOURS=12

# --- Strata Cloud Manager (required for deploys) --------------------------------
# --- How the firewall is managed -----------------------------------------------
# scm: managed by Strata Cloud Manager. Bypasses are created in SCM and pushed.
# local: configured on the firewall itself (not by SCM or Panorama). Bypasses
# are created on the firewall and committed.
MANAGEMENT=scm

# --- Strata Cloud Manager (MANAGEMENT=scm only) ----------------------------------
# A service account (Settings > Identity & Access > Add Identity > Service
# Account) with a role that can edit configuration and push.
# See docs/prerequisites.md.
Expand All @@ -18,11 +24,15 @@ SCM_SCOPE=tsg_id:1234567890
# SCM_HOST=api.sase.paloaltonetworks.com
# SCM_AUTH_URL=https://auth.apps.paloaltonetworks.com/auth/v1/oauth2/access_token

# --- Firewall (required for the decryption log viewer) --------------------------
# --- Firewall (required) ---------------------------------------------------------
# Management address of the firewall; must match a name in its certificate.
FIREWALL_HOST=firewall.example.com
# XML API key for an admin that can read logs (see docs/prerequisites.md).
# XML API key. With MANAGEMENT=scm it only needs to read logs; with
# MANAGEMENT=local it also changes config and commits (see docs/prerequisites.md).
FIREWALL_API_KEY=
# MANAGEMENT=local only: the admin that owns FIREWALL_API_KEY. Commits include
# only this admin's changes.
# FIREWALL_USERNAME=decrypt-bypass
# Timezone the firewall writes log timestamps in.
FIREWALL_TIMEZONE=UTC
# If the management certificate comes from a private CA, mount the CA file
Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ body:
id: logs
attributes:
label: Logs or error messages
description: From the deploy panel's log, `docker logs scm-decrypt-bypass`, or the CLI. Redacted, please.
description: From the deploy panel's log, `docker logs panos-decrypt-bypass`, or the CLI. Redacted, please.
render: text
- type: input
id: version
attributes:
label: Version
description: Shown at the bottom of the web GUI, or `scm-decrypt-bypass version`.
description: Shown at the bottom of the web GUI, or `panos-decrypt-bypass version`.
validations:
required: true
- type: dropdown
Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/Former-Stranger/scm-decrypt-bypass/security/advisories/new
url: https://github.com/Former-Stranger/panos-decrypt-bypass/security/advisories/new
about: Report security issues privately.
- name: Documentation
url: https://github.com/Former-Stranger/scm-decrypt-bypass/tree/main/docs
url: https://github.com/Former-Stranger/panos-decrypt-bypass/tree/main/docs
about: Setup, configuration and troubleshooting guides.
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ updates:
schedule:
interval: weekly
- package-ecosystem: terraform
directory: /src/scm_decrypt_bypass/terraform
directory: /src/panos_decrypt_bypass/terraform
schedule:
interval: weekly
45 changes: 29 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.12", "3.13"]
python: ["3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@v10.3.0
Expand All @@ -36,21 +36,27 @@ jobs:
run: uv run python -m unittest discover tests -v

terraform:
# Job name stays "Terraform" (a required check); one step per module.
name: Terraform
runs-on: ubuntu-latest
defaults:
run:
working-directory: src/scm_decrypt_bypass/terraform
steps:
- uses: actions/checkout@v7
- uses: hashicorp/setup-terraform@v4
with:
terraform_wrapper: false
- run: terraform fmt -check -recursive
- run: terraform init -backend=false -input=false -lockfile=readonly
- run: terraform validate
- name: Test (mocked provider)
run: terraform test
- run: terraform fmt -check -recursive src/panos_decrypt_bypass/terraform
- name: SCM module (validate, mocked-provider tests)
working-directory: src/panos_decrypt_bypass/terraform/scm
run: |
terraform init -backend=false -input=false -lockfile=readonly
terraform validate
terraform test
- name: Local firewall module (validate, mocked-provider tests)
working-directory: src/panos_decrypt_bypass/terraform/local
run: |
terraform init -backend=false -input=false -lockfile=readonly
terraform validate
terraform test

docker:
name: Docker image
Expand All @@ -62,20 +68,27 @@ jobs:
with:
context: .
load: true
tags: scm-decrypt-bypass:ci
tags: panos-decrypt-bypass:ci
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Smoke test (demo mode)
run: |
docker run -d --name sdb -p 8088:8088 -e WEBGUI_DEMO=1 -e WEBGUI_PASSWORD=ci-password-1234 scm-decrypt-bypass:ci
docker run -d --name pdb -p 8088:8088 -e WEBGUI_DEMO=1 -e WEBGUI_PASSWORD=ci-password-1234 panos-decrypt-bypass:ci
for i in $(seq 1 30); do
[ "$(docker inspect -f '{{.State.Health.Status}}' sdb)" = healthy ] && break
[ "$(docker inspect -f '{{.State.Health.Status}}' pdb)" = healthy ] && break
sleep 2
done
docker inspect -f '{{.State.Health.Status}}' sdb | grep -qx healthy
docker inspect -f '{{.State.Health.Status}}' pdb | grep -qx healthy
curl -fsS http://127.0.0.1:8088/healthz
test "$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8088/api/status)" = 401
docker exec sdb terraform version
docker exec sdb scm-decrypt-bypass version
docker exec pdb terraform version
docker exec pdb panos-decrypt-bypass version
- name: Both modules initialise offline from the bundled providers
run: |
for module in scm local; do
docker run --rm --network none --entrypoint sh panos-decrypt-bypass:ci -c "
cp -r \"\$(python -c 'from panos_decrypt_bypass.workspace import TERRAFORM_DIR; print(TERRAFORM_DIR)')/$module\" /tmp/tf &&
cd /tmp/tf && terraform init -backend=false -input=false -lockfile=readonly -no-color"
done
- if: failure()
run: docker logs sdb
run: docker logs pdb
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ jobs:
uses: docker/metadata-action@v6
with:
images: |
ghcr.io/former-stranger/scm-decrypt-bypass
name=docker.io/${{ env.DOCKERHUB_NAMESPACE }}/scm-decrypt-bypass,enable=${{ env.DOCKERHUB_USERNAME != '' }}
ghcr.io/former-stranger/panos-decrypt-bypass
name=docker.io/${{ env.DOCKERHUB_NAMESPACE }}/panos-decrypt-bypass,enable=${{ env.DOCKERHUB_USERNAME != '' }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
Expand All @@ -75,7 +75,7 @@ jobs:

- uses: actions/attest-build-provenance@v4
with:
subject-name: ghcr.io/former-stranger/scm-decrypt-bypass
subject-name: ghcr.io/former-stranger/panos-decrypt-bypass
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true

Expand Down
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@ All notable changes are listed here. The format follows

## [Unreleased]

## [0.2.0] - 2026-10-15

### Added
- Support for locally managed firewalls (`MANAGEMENT=local`): a second
Terraform module, using the PaloAltoNetworks/panos provider, creates the
same URL category, address objects, tag, EDLs, profile and no-decrypt
rules in a vsys on the firewall, and the app commits them over the XML
API. Commits include only `FIREWALL_USERNAME`'s changes. One-click
bypasses, review, retry and the CLI work as with SCM.
- `FIREWALL_CA_FILE` is also trusted by Terraform in local mode.
- `panos-decrypt-bypass commit` as an alias of `push`.
- `panos-decrypt-bypass terraform <args>` runs any Terraform command with the
app's settings, for `destroy`, `import` and state commands.
- The status area now flags missing SCM or firewall settings for the
selected mode.

### Changed
- **Renamed from scm-decrypt-bypass to panos-decrypt-bypass**: the
repository, images (`ghcr.io/former-stranger/panos-decrypt-bypass`,
`docker.io/formerstranger/panos-decrypt-bypass`), CLI command, Python
package and compose service. `PDB_VERSION` replaces `SDB_VERSION`. See
[upgrading from 0.1.0](docs/installation.md#upgrading-from-scm-decrypt-bypass-010).
- The bypass tag's comment now names panos-decrypt-bypass, so the first
deploy after upgrading shows it as a change to review.
- Signing in again is needed once, because the session cookie was renamed.
- The SCM Terraform module moved to `terraform/scm/`. Data directories are
migrated automatically, and module files from older versions are removed.

### Notes
- Decryption exclusions (`exclusion-hostnames.txt`) remain SCM-only. On a
locally managed firewall they're ignored with a warning.

## [0.1.0] - 2026-10-14

First public release.
Expand Down
24 changes: 15 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ You need [uv](https://docs.astral.sh/uv/) and
[Terraform](https://developer.hashicorp.com/terraform/install) 1.9 or newer.

```bash
git clone https://github.com/Former-Stranger/scm-decrypt-bypass.git
cd scm-decrypt-bypass
git clone https://github.com/Former-Stranger/panos-decrypt-bypass.git
cd panos-decrypt-bypass
uv sync
```

Run the GUI with sample data and simulated deploys (nothing is sent anywhere).
The password below is for this local demo only:

```bash
WEBGUI_DEMO=1 WEBGUI_PASSWORD=demo-password-1234 uv run scm-decrypt-bypass serve
WEBGUI_DEMO=1 WEBGUI_PASSWORD=demo-password-1234 uv run panos-decrypt-bypass serve
```

Then open http://127.0.0.1:8088.
Expand All @@ -30,24 +30,30 @@ CI runs all of these on every pull request:
uv run ruff check src tests
uv run ruff format --check src tests
uv run python -m unittest discover tests
terraform -chdir=src/scm_decrypt_bypass/terraform init -backend=false
terraform -chdir=src/scm_decrypt_bypass/terraform test
docker build -t scm-decrypt-bypass:dev .
for m in scm local; do
terraform -chdir=src/panos_decrypt_bypass/terraform/$m init -backend=false
terraform -chdir=src/panos_decrypt_bypass/terraform/$m test
done
docker build -t panos-decrypt-bypass:dev .
```

The Python tests use a fake `terraform` and a fake firewall, so they never
touch SCM or a real firewall. `terraform test` uses a mocked provider.
`terraform/scm/lists.tf` and `terraform/local/lists.tf` must stay identical; a
test checks.

## Project layout

```
src/scm_decrypt_bypass/
src/panos_decrypt_bypass/
cli.py command line and interactive menu
bypass_lists.py reading, validating and editing the bypass lists
scm_api.py SCM config push and job polling
panos_commit.py commit on a locally managed firewall (MANAGEMENT=local)
workspace.py the data directory and Terraform working directory
terraform/ the Terraform module (and its tests/)
templates/ starter bypass lists and terraform.tfvars
terraform/scm/ Terraform module for Strata Cloud Manager (and its tests/)
terraform/local/ Terraform module for a locally managed firewall (and its tests/)
templates/ starter bypass lists and a terraform.tfvars per mode
web/ FastAPI app, log poller, deployer, login, static page
tests/ Python tests and fixtures
docs/ user documentation
Expand Down
26 changes: 14 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
# scm-decrypt-bypass: web GUI + CLI, with Terraform and the SCM provider built in.
# panos-decrypt-bypass: web GUI + CLI, with Terraform and the SCM and PAN-OS providers built in.
FROM python:3.14-slim

ARG TERRAFORM_VERSION=1.16.6
Expand Down Expand Up @@ -28,14 +28,16 @@ RUN uv sync --locked --no-dev --no-install-project
COPY src ./src
RUN uv sync --locked --no-dev --no-editable

# Pre-install the SCM provider into a local mirror and point Terraform at it,
# so `terraform init` never needs the registry at runtime.
# Pre-install the SCM and PAN-OS providers into a local mirror and point
# Terraform at it, so `terraform init` never needs the registry at runtime.
RUN mkdir -p /opt/terraform/providers \
&& cp -r /app/src/scm_decrypt_bypass/terraform /tmp/tf-module \
&& cd /tmp/tf-module \
&& terraform init -backend=false -input=false -no-color > /dev/null \
&& terraform providers mirror -platform=linux_${TARGETARCH:-amd64} /opt/terraform/providers \
&& cd / && rm -rf /tmp/tf-module /tmp/.terraform.d \
&& for module in scm local; do \
cp -r /app/src/panos_decrypt_bypass/terraform/$module /tmp/tf-module \
&& (cd /tmp/tf-module && terraform init -backend=false -input=false -no-color > /dev/null \
&& terraform providers mirror -platform=linux_${TARGETARCH:-amd64} /opt/terraform/providers) \
&& rm -rf /tmp/tf-module || exit 1; \
done \
&& rm -rf /tmp/.terraform.d \
&& printf '%s\n' \
'provider_installation {' \
' filesystem_mirror {' \
Expand Down Expand Up @@ -65,9 +67,9 @@ HEALTHCHECK --interval=30s --timeout=5s --start-period=20s \
CMD ["python", "-c", "import os, urllib.request; urllib.request.urlopen('http://127.0.0.1:' + os.environ.get('WEBGUI_PORT', '8088') + '/healthz', timeout=3)"]

ENTRYPOINT ["entrypoint"]
CMD ["scm-decrypt-bypass", "serve"]
CMD ["panos-decrypt-bypass", "serve"]

LABEL org.opencontainers.image.title="scm-decrypt-bypass" \
org.opencontainers.image.description="Find TLS decryption failures on Palo Alto Networks firewalls and bypass them through Strata Cloud Manager" \
org.opencontainers.image.source="https://github.com/Former-Stranger/scm-decrypt-bypass" \
LABEL org.opencontainers.image.title="panos-decrypt-bypass" \
org.opencontainers.image.description="Find TLS decryption failures on Palo Alto Networks firewalls and bypass them in one click, through Strata Cloud Manager or on the firewall itself" \
org.opencontainers.image.source="https://github.com/Former-Stranger/panos-decrypt-bypass" \
org.opencontainers.image.licenses="MIT"
Loading
Loading