New subcommand that connects to a chosen kube context and walks the
user through three picker steps before writing forwards to the config:
1. Namespace multi-select (no system-namespace exclusion)
2. Service multi-select grouped by namespace, with already-configured
rows greyed out and locked off
3. Starting-port input with a live preview of consecutive local-port
assignments, skipping any port already taken by the existing config
or another row in the batch
Multi-port services emit one forward per port. Non-TCP ports are
skipped with a one-line warning at the end (kportal forward layer is
TCP-only). --dry-run prints the planned forwards without writing.
Subcommand dispatch lives in cmd/kportal/main.go: when os.Args[1] ==
'generate', runGenerate(os.Args[2:]) is invoked before the main
flag.Parse() so the flag.NewFlagSet 'generate' parses its own
'--context', '--config', '--dry-run' flags. Invalid contexts list
the available ones for quick correction.
Tests in internal/ui/generate_test.go cover:
- namespace toggle / toggle-all / filter
- service multi-select with locked already-configured rows and
non-TCP filtering
- port-collision-aware consecutive assignment using a real Mutator
against a tempdir config
- reject + recover for starting-port < 1024
- dry-run does not invoke the mutator
- end-to-end Update() walk through the three steps
- parse-starting-port boundary table
- port-step view rendering
- ServiceCandidate.Key() determinism
README updated with a 'Generate Forwards from a Cluster' section
describing the flow and the three flags.
Releases are signed by the lukaszraczylo/shared-actions reusable
workflow, so the Sigstore certificate subject is the workflow URL
rather than this repo. The previous regex
'https://github.com/lukaszraczylo/kportal/.*' never matched, so any
user with cosign installed would see verification fail and abort
the install.
Pin cert-identity to the exact workflow URL:
^https://github\.com/lukaszraczylo/shared-actions/\.github/workflows/go-release\.yaml@refs/heads/main$
Override via COSIGN_CERT_IDENTITY_REGEXP for forks of the release
pipeline. Same fix applied to README's manual verification example.
Verified end-to-end against release v0.2.90:
cosign verify-blob ... -> Verified OK
P0 #8 — install.sh fetched and installed the binary with no integrity
check whatsoever, despite README claiming cosign verification. A
compromised release or registry MITM resulted in RCE on every
installer.
Now:
- downloads checksums.txt alongside the archive (required; abort on
missing)
- computes local SHA-256 with shasum -a 256 (works on macOS+Linux,
not GNU-only sha256sum)
- aborts on mismatch with a clear error
- if cosign is in PATH AND the sigstore bundle is present (the latter
already published by goreleaser), verifies cert-identity. Skipped
silently when cosign is absent so the install path still works for
users without cosign installed.
- SKIP_COSIGN=1 lets users opt out of cosign verification only
(checksum verification is always enforced).
- DRY_RUN=1 verifies + downloads but does not install, for testing.
Also replaced GNU-only `grep -oP` (silently fails on macOS BSD grep)
with portable awk for parsing kportal --version.
NOTE: the cosign cert-identity regex matches lukaszraczylo/kportal/.*
but actual releases are signed from the shared-actions reusable
workflow. Users with cosign installed will currently see a verification
failure on real releases. Either widen the regex to lukaszraczylo/.*
or change the signing identity scheme — flagging for follow-up.
README install section updated to mention the new verification.