{"id":51675001,"url":"https://github.com/rupivbluegreen/omni-sag","last_synced_at":"2026-07-15T04:33:53.600Z","repository":{"id":371330213,"uuid":"1300191000","full_name":"rupivbluegreen/omni-sag","owner":"rupivbluegreen","description":"Omni-SAG — auditable Linux privileged-access gateway (SSH + SFTP): AD+MFA, single-dialer authz, tamper-evident evidence chain, recording, ICAP inspection, CyberArk injection, four-eyes approvals, control-plane API/TUI. Go modular monolith.","archived":false,"fork":false,"pushed_at":"2026-07-14T13:06:31.000Z","size":972,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-14T15:07:30.030Z","etag":null,"topics":["audit-log","bastion","devsecops","golang","pam","privileged-access","security","sftp","ssh","ssh-gateway","zero-trust"],"latest_commit_sha":null,"homepage":"https://rupivbluegreen.github.io/omni-sag/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rupivbluegreen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-14T08:04:33.000Z","updated_at":"2026-07-14T13:07:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rupivbluegreen/omni-sag","commit_stats":null,"previous_names":["rupivbluegreen/omni-sag"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/rupivbluegreen/omni-sag","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupivbluegreen%2Fomni-sag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupivbluegreen%2Fomni-sag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupivbluegreen%2Fomni-sag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupivbluegreen%2Fomni-sag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rupivbluegreen","download_url":"https://codeload.github.com/rupivbluegreen/omni-sag/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rupivbluegreen%2Fomni-sag/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35490692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-15T02:00:06.706Z","response_time":131,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit-log","bastion","devsecops","golang","pam","privileged-access","security","sftp","ssh","ssh-gateway","zero-trust"],"created_at":"2026-07-15T04:33:52.786Z","updated_at":"2026-07-15T04:33:53.595Z","avatar_url":"https://github.com/rupivbluegreen.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"docs/assets/logo.svg\" alt=\"Omni-SAG\" width=\"440\" /\u003e\n\n### the SSH bastion that keeps the receipts\n\n*Your servers' bouncer. Every login checked, every tunnel authorized, every byte accounted for —\nwith a tamper-evident paper trail you can verify offline, even with the gateway switched off.*\n\n[![CI](https://github.com/rupivbluegreen/omni-sag/actions/workflows/ci.yml/badge.svg)](https://github.com/rupivbluegreen/omni-sag/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-ffb000.svg)](LICENSE)\n[![Go 1.25](https://img.shields.io/badge/go-1.25-00ADD8.svg)](go.mod)\n[![fails](https://img.shields.io/badge/fails-closed%20on%20purpose-ff6b6b.svg)](docs/audit/fail-closed-matrix.md)\n[![reviewed](https://img.shields.io/badge/reviewed-adversarially-57d98a.svg)](#-how-it-was-built)\n[![PRs welcome](https://img.shields.io/badge/PRs-welcome-ffb000.svg)](CONTRIBUTING.md)\n\n**[🌐 Website](https://rupivbluegreen.github.io/omni-sag/) · [🚀 Quickstart](#-60-seconds-to-whoa) · [🧾 Audit pack](docs/audit/) · [🗺️ Roadmap](#️-roadmap)**\n\n\u003c/div\u003e\n\n---\n\n## 👋 What even is this?\n\nPoint your team at **Omni-SAG** instead of straight at your boxes. It authenticates them against\nActive Directory (with MFA), decides what they're allowed to reach, and writes down *everything* in\na way nobody can quietly edit later. The default answer is always **no** — access is something you\nearn, per connection.\n\nIt's **open source**, built in the open for anyone who thinks privileged access should come with\nreceipts. No enterprise sales call required. 🙂\n\n```console\n$ ssh -L 5432:db1.lab.local:5432 alice@gateway     # alice ∈ dba\n✔ ALLOWED · role=dba · tunnel open · evidence: tunnel_decision allow=true\n\n$ ssh -L 5432:db1.lab.local:5432 bob@gateway       # bob ∉ dba\n✘ administratively prohibited · evidence: tunnel_decision allow=false\n\n$ omni-verify -bundle ./evidence -pubkey $KEY\nPASS — evidence bundle is intact and authentic.\n# flip one byte…\nFAIL — TAMPER: record hash mismatch. loudly.\n```\n\nThat's not a mockup — it's a real recorded run: **[▶ watch it live](https://rupivbluegreen.github.io/omni-sag/#start)**\n(same lab, same two users, same tamper — the raw [asciicast](docs/assets/demo.cast) is in the repo too).\n\n## ✨ Features\n\n| | |\n|---|---|\n| 🔐 **AD + MFA** | LDAPS against Active Directory, then RADIUS MS-CHAPv2 (never PAP). |\n| 🎯 **One dialer, one rule** | A single authorized path to targets, with an **SSRF guard** (blocks the metadata IP, loopback, DNS rebinding). |\n| 🧾 **Tamper-evident evidence** | Per-emitter epoch+sequence, Merkle chain, Ed25519 signed checkpoints, WORM archive — verify offline with `omni-verify`. |\n| 🎥 **Session recording** | Asciicast recording (replay in the TUI). Forwarding is **refused** on must-record targets. |\n| 🦠 **Content inspection** | SFTP uploads streamed through ICAP (AV/DLP). Blocked or unscannable → quarantined, transfer refused. |\n| 🔑 **CyberArk injection** | Just-in-time secret fetch; the user never sees it. Vault down = refused. **No silent downgrade.** |\n| 👀 **Four-eyes approvals** | Crown-jewel targets block until a *second* human approves (never yourself). Live supervision + kill switch. |\n| 🛰️ **API + TUI** | OpenAPI control plane + a Bubble Tea terminal UI. Kill the API? SSH keeps running — it's genuinely out-of-band. |\n| 📦 **Ships nicely** | UBI9 non-root image, Helm chart (restricted-v2), graceful drain, Prometheus metrics, SBOM + cosign, FIPS mode. |\n\n## 🚀 60 seconds to \"whoa\"\n\nSpins up a throwaway lab (Samba AD, MinIO, FreeRADIUS), then two SSH users where only the DBA gets\nthe tunnel — with both attempts in the evidence log.\n\n```bash\ngit clone https://github.com/rupivbluegreen/omni-sag\ncd omni-sag\n\nmake lab-up        # samba-AD + MinIO + FreeRADIUS\nmake lab-seed      # create alice (dba) and bob (not)\nmake binaries      # build omni-sag, omnisag-ctl, omni-verify\n\n./bin/omni-sag_linux_amd64 -config deploy/compose/config.example.yaml\n# ssh -L 5432:db1.lab.local:5432 alice@gw  → allowed\n# ssh -L 5432:db1.lab.local:5432 bob@gw    → administratively prohibited\n# ./bin/omni-verify_linux_amd64 -bundle ./evidence   → PASS (tamper a byte → FAIL)\n```\n\nRequirements: **Go 1.25+**, **Docker** (for the lab), and an SSH client. `make lab-down` to clean up.\n\n## 🧠 How it works\n\nA **modular monolith** with CI-enforced package boundaries — comprehensible, without the\ndistributed-systems tax.\n\n```\nclient ──ssh──▶ [ session ] ──▶ authn + ratelimit ──▶ policy ──▶ [ dialer ] ──▶ target\n                     │                                    │  (the ONLY socket to a target,\n                     ▼                                    ▼   authorized + SSRF-guarded first)\n                [ evidence ] ── hash-chain · Merkle · Ed25519 · WORM ──▶ omni-verify (offline)\n\n─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  out-of-band control plane  ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─\noperator ──mTLS──▶ [ api ] ──▶ sessions · policy · approvals · supervision\n                     ▲                       (the data path never imports this)\n                omnisag-ctl / TUI\n```\n\n**Load-bearing invariants** (each CI- or test-enforced):\n\n1. **Single dialer** — only `internal/dialer` opens sockets to targets, authorized *before* the socket.\n2. **Fail closed** — any dependency failure denies. Proven by a [29-row fail-closed matrix](docs/audit/fail-closed-matrix.md).\n3. **No silent credential downgrade** — `inject` failure refuses; never falls back to prompt/passthrough.\n4. **Evidence is non-optional \u0026 tamper-evident** — and emit errors are surfaced, never swallowed.\n5. **Secrets never become Go strings** — `[]byte` only, zeroized ([ADR-0001](docs/decisions/0001-mlock-free-credential-handling.md)).\n6. **Four-eyes** — approver ≠ requester, server-side, durable across restarts.\n7. **Control plane out-of-band** — kill the API, SSH keeps serving. (It's a test, not a slogan.)\n\n## 🏗️ How it was built\n\n13 thin slices, **0 → GA**, each one demoable on its own — no five-half-finished-branches energy.\nEvery slice went through an **adversarial review gate** before the next one started, and a few of\nthose reviews caught real bugs. That's the point.\n\n- **6** real bugs caught by review/hardening (an ICAP OOM, a policy-eval contract slip, an\n  inspection fail-open, an SFTP inspection-gap bypass, …) — all fixed, all regression-locked.\n- A final **12-auditor sweep** (adversarially verified) before calling it v1.\n- Full story + slice map on the [website](https://rupivbluegreen.github.io/omni-sag/) and in\n  [`docs/audit/`](docs/audit/).\n\n## 🗺️ Roadmap\n\n- **v1 (here):** SSH + SFTP, AD+MFA, dialer authz, evidence chain, recording, inspection,\n  CyberArk, approvals, API + TUI + packaging. ✅\n- **v1.x:** real SFTP backend \u0026 target-shell proxy, SSH certificate authority, Kerberos/GSSAPI,\n  OIDC-primary MFA, CRD informers, TLS-config FIPS routing.\n- **v2:** RDP (native mstsc, then browser RDP with recording).\n- **Never:** shared-process multi-tenancy, monetization machinery in the OSS, semantic command\n  reconstruction from pixels.\n\n## 🤝 Contributing\n\nIssues, ideas, and PRs all welcome — see **[CONTRIBUTING.md](CONTRIBUTING.md)** and the\n[Code of Conduct](CODE_OF_CONDUCT.md). Found a security issue? Please read\n**[SECURITY.md](SECURITY.md)** first (don't file it as a public issue). New here? Look for\n[`good first issue`](https://github.com/rupivbluegreen/omni-sag/labels/good%20first%20issue).\n\n## 📜 License\n\n[MIT](LICENSE) — do fun things with it.\n\n\u003cdiv align=\"center\"\u003e\n\n*Made with too much coffee and a healthy distrust of default-allow.* ☕\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frupivbluegreen%2Fomni-sag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frupivbluegreen%2Fomni-sag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frupivbluegreen%2Fomni-sag/lists"}