Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3462f6b
feat: allow free-form cloud regions and add cluster discovery metadata
JLCode-tech Aug 31, 2026
f0efbe4
feat: enrich BNK Health dashboard with node/AZ placement metadata
JLCode-tech Aug 31, 2026
b4d8770
refactor: DRY operator connectivity, node enrichment, and region sele…
JLCode-tech Aug 31, 2026
9c856b3
feat: BNK Health dashboard connectivity and integration status
JLCode-tech Aug 31, 2026
d37dfec
feat: credential-template-driven cluster auto-detection
JLCode-tech Aug 31, 2026
0bd5c03
feat: add BNK Resources fleet consumption dashboard to System page
JLCode-tech Aug 31, 2026
ce6af75
refactor: relocate BNK Resources, MCP, and Benchmarks navigation
JLCode-tech Sep 1, 2026
447ebb9
feat: add TMM traffic stats to BNK gateway/listener/egress views
JLCode-tech Sep 1, 2026
c3c7b3f
feat: add operational-state polish to App Delivery (Slice 7)
JLCode-tech Sep 1, 2026
3003bb2
feat: support custom TLS CA certificates for corporate SSL inspection…
JLCode-tech Sep 1, 2026
0a0d4a4
fix(module-library): honor git_ref tag refs and reconcile official so…
JLCode-tech Sep 1, 2026
09fd3fa
perf(f5bnk): stop blocking health dashboard on unified data; skip con…
JLCode-tech Sep 1, 2026
1daf256
perf(system): parallelize bnk-consumption cluster collection with 30s…
JLCode-tech Sep 1, 2026
4c2f6a1
fix(f5bnk): evaluate BNK 2.3 policy refs, route parent conditions, an…
JLCode-tech Sep 1, 2026
5c607a1
perf(bnk): cap thread pools and cache expensive cloud/BNK/license work
JLCode-tech Sep 1, 2026
1946806
feat(k8s): expose cluster metadata fields end-to-end
JLCode-tech Sep 1, 2026
b7b96da
test(f5bnk): return real cluster from mocked KubernetesService.get_cl…
JLCode-tech Sep 1, 2026
1f42cf7
perf(bnk): cache shared BNK state across tabs, diagnostics, and licen…
JLCode-tech Sep 1, 2026
779b0d6
feat(f5bnk): show per-listener connection counters in Traffic Flow
JLCode-tech Sep 1, 2026
4c64318
feat(system): add node capacity fallback for bnk resources and polish…
JLCode-tech Sep 2, 2026
cc9b187
perf(k8s,f5bnk,fleet): eliminate blocking spinners and redundant fetc…
JLCode-tech Sep 2, 2026
59adebc
perf: optimize F5 BNK diagnostics data caching and cross-tab navigation
JLCode-tech Sep 2, 2026
935b3b8
fix(ci): suppress upstream CVE-2026-56854 in bundled Go binaries
JLCode-tech Sep 2, 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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ docker-compose.override.yml
# OPT-001: Smart build script stores last-build commit hash
.build-hash

# Custom TLS CA certificates (corporate proxy certs, etc.)
# The certs/ directory itself is tracked (see certs/.gitkeep), but certificate
# files should never be committed.
/certs/*.crt
/certs/*.pem
/certs/*.cer
/certs/*.der

# Environment variables
.env
.env.local
Expand Down
10 changes: 10 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ CVE-2024-45337 exp:2026-11-30
# Added: 2026-04-15
CVE-2026-33186 exp:2026-11-30

# CVE-2026-56854: golang.org/x/crypto/ssh - Authentication bypass due to unenforced source-address restrictions
# Affects: helm, oras, and tofu binaries bundled into Docker images (golang.org/x/crypto v0.31.0 - v0.46.0)
# Fixed in: golang.org/x/crypto >= 0.55.0
# Not exploitable in our context: Forge invokes client CLI commands against Kubernetes APIs and
# OCI/container registries. No container runs an SSH server or accepts incoming SSH connections.
# Status: Waiting for upstream helm, oras, and opentofu releases built with patched golang.org/x/crypto.
# Added: 2026-09-02
CVE-2026-56854 exp:2026-11-30


# CVE-2026-7598: libssh2 — integer overflow via large username/password
# Affects: libssh2-1t64 1.11.1-1 in Debian trixie base image
# Pulled in transitively (git/curl/apt deps); not directly used by Forge —
Expand Down
34 changes: 34 additions & 0 deletions backend/alembic/versions/v2_156_add_cluster_discovery_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Add account_id and discovery_status to kubernetes_clusters.

Revision ID: v2_156
Revises: v2_155

Adds cloud-account metadata and a coarse discovery status to the
KubernetesCluster table so that fleet-health and cluster-list views can
surface per-cluster cloud context (account/subscription) and discovery
state without extra joins.
"""
import sqlalchemy as sa

from alembic import op

revision = "v2_156"
down_revision = "v2_155"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.add_column(
"kubernetes_clusters",
sa.Column("account_id", sa.String(length=100), nullable=True),
)
op.add_column(
"kubernetes_clusters",
sa.Column("discovery_status", sa.String(length=50), nullable=True),
)


def downgrade() -> None:
op.drop_column("kubernetes_clusters", "discovery_status")
op.drop_column("kubernetes_clusters", "account_id")
48 changes: 48 additions & 0 deletions backend/alembic/versions/v2_157_add_cluster_metadata_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Add cluster metadata fields to kubernetes_clusters.

Revision ID: v2_157
Revises: v2_156

Adds node_count, connectivity_status, integration_status, zones, and
access_method so cluster list/detail views can surface per-cluster
metadata without extra joins or probes.
"""
import sqlalchemy as sa

from alembic import op

revision = "v2_157"
down_revision = "v2_156"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.add_column(
"kubernetes_clusters",
sa.Column("node_count", sa.Integer(), nullable=True),
)
op.add_column(
"kubernetes_clusters",
sa.Column("connectivity_status", sa.String(length=50), nullable=True),
)
op.add_column(
"kubernetes_clusters",
sa.Column("integration_status", sa.String(length=50), nullable=True),
)
op.add_column(
"kubernetes_clusters",
sa.Column("zones", sa.JSON(), nullable=True),
)
op.add_column(
"kubernetes_clusters",
sa.Column("access_method", sa.String(length=50), nullable=True),
)


def downgrade() -> None:
op.drop_column("kubernetes_clusters", "access_method")
op.drop_column("kubernetes_clusters", "zones")
op.drop_column("kubernetes_clusters", "integration_status")
op.drop_column("kubernetes_clusters", "connectivity_status")
op.drop_column("kubernetes_clusters", "node_count")
35 changes: 35 additions & 0 deletions backend/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,41 @@ echo "================================================"
echo "BNK-Forge Backend Startup"
echo "================================================"

# Install user-supplied TLS CA certificates (e.g. corporate SSL inspection proxy).
# Corporate proxies re-sign outbound TLS (GitHub, Docker Hub, cloud APIs) with an
# internal CA that is not shipped in the public ca-certificates package. Mounting
# those CA files into /app/certs lets Forge trust them without baking them into
# the image or disabling certificate verification.
#
# The entrypoint runs as the non-root bnkforge user, so we cannot update the
# system-wide store. Instead we build a per-user bundle and export the standard
# environment variables that git, Python requests/urllib3, curl, Go binaries
# (Helm, OpenTofu), and the AWS CLI honor.
CUSTOM_CERT_DIR="/app/certs"
CUSTOM_BUNDLE="/home/bnkforge/.bnk-forge-ca-bundle.crt"
if [ -d "$CUSTOM_CERT_DIR" ]; then
installed_count=0
for cert in "$CUSTOM_CERT_DIR"/*.crt "$CUSTOM_CERT_DIR"/*.pem "$CUSTOM_CERT_DIR"/*.cer "$CUSTOM_CERT_DIR"/*.der; do
[ -e "$cert" ] || continue
installed_count=$((installed_count + 1))
done
if [ "$installed_count" -gt 0 ]; then
echo "Installing $installed_count custom CA certificate(s) from $CUSTOM_CERT_DIR"
# Start from the current system bundle, then append custom certs.
cp /etc/ssl/certs/ca-certificates.crt "$CUSTOM_BUNDLE"
for cert in "$CUSTOM_CERT_DIR"/*.crt "$CUSTOM_CERT_DIR"/*.pem "$CUSTOM_CERT_DIR"/*.cer "$CUSTOM_CERT_DIR"/*.der; do
[ -e "$cert" ] || continue
cat "$cert" >> "$CUSTOM_BUNDLE"
done
# Make the bundle available to common TLS consumers.
export SSL_CERT_FILE="$CUSTOM_BUNDLE"
export GIT_SSL_CAINFO="$CUSTOM_BUNDLE"
# curl and Node/Go tooling may also honor these.
export CURL_CA_BUNDLE="$CUSTOM_BUNDLE"
export REQUESTS_CA_BUNDLE="$CUSTOM_BUNDLE"
fi
fi

# Fix volume permissions on first run
# Docker volumes are created as root, but we run as bnkforge (uid 1000)
# The Makefile install target handles permissions, but we also check here
Expand Down
7 changes: 7 additions & 0 deletions backend/models/kubernetes.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class KubernetesCluster(Base):
kubeconfig_encrypted = Column(Text, nullable=True) # Base64 encoded encrypted kubeconfig
cloud_provider = Column(String(50)) # aws, azure, gcp, on-prem
region = Column(String(100)) # Cloud region
account_id = Column(String(100), nullable=True) # Cloud account / subscription ID
discovery_status = Column(String(50), nullable=True) # pending/probing/completed/failed
node_count = Column(Integer, nullable=True)
connectivity_status = Column(String(50), nullable=True) # connected/reachable/partial/unreachable/unknown
integration_status = Column(String(50), nullable=True) # agent_connected/agent_disconnected/direct
zones = Column(JSON, nullable=True) # List of availability zones from nodes
access_method = Column(String(50), nullable=True) # kubeconfig/ssh_tunnel/operator
default_namespace = Column(String(255), default="default")

# PLATFORM-CONTEXT-002: detected cluster platform context (additive)
Expand Down
Loading
Loading