From 9624068c082ec211a9de8ac7e32e1096aa4935da Mon Sep 17 00:00:00 2001 From: mahesh bhatiya Date: Wed, 10 Sep 2025 22:01:01 +0530 Subject: [PATCH] docs: add project documentation and update --- .gitignore | 99 ++++++-- CHANGELOG.md | 48 ++++ Cargo.lock | 48 +--- Cargo.toml | 3 +- LICENSE | 21 ++ README.md | 228 +++++++++++------ bin/ebpf.o | Bin 2776 -> 0 bytes bin/ebpf.so | Bin 1312 -> 0 bytes bin/simple_trace.o | Bin 0 -> 3608 bytes bin/simple_xdp.o | Bin 0 -> 4568 bytes bin/xdp_pass_kern.o | Bin 720 -> 0 bytes ebpf-demo/Cargo.lock | 119 --------- ebpf-demo/Cargo.toml | 5 - ebpf-demo/user/Cargo.toml | 10 - ebpf-demo/user/src/main.rs | 3 - ebpf-demo/xdp_drop/.cargo/config.toml | 5 - ebpf-demo/xdp_drop/Cargo.toml | 12 - ebpf-demo/xdp_drop/src/lib.rs | 15 -- ebpf-demo/xdp_drop/src/main.rs | 26 -- ebpf-demo/xdp_pass_kern.c | 12 - ebpf-demo/xdp_pass_kern.o | Bin 720 -> 0 bytes eclipta-cli/src/commands/ebpf/load.rs | 92 +++++++ eclipta.yaml | 353 ++++++++++++++++++++++++++ examples/ebpf/Makefile | 33 +++ examples/ebpf/simple_trace.c | 14 + examples/ebpf/simple_xdp.c | 14 + install.sh | 114 ++++++--- tests/ebpf_loader | Bin 32560 -> 0 bytes tests/loader.c | 237 ----------------- tests/xdp_pass_kern.o | Bin 720 -> 0 bytes 30 files changed, 887 insertions(+), 624 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 LICENSE delete mode 100644 bin/ebpf.o delete mode 100644 bin/ebpf.so create mode 100644 bin/simple_trace.o create mode 100644 bin/simple_xdp.o delete mode 100644 bin/xdp_pass_kern.o delete mode 100644 ebpf-demo/Cargo.lock delete mode 100644 ebpf-demo/Cargo.toml delete mode 100644 ebpf-demo/user/Cargo.toml delete mode 100644 ebpf-demo/user/src/main.rs delete mode 100644 ebpf-demo/xdp_drop/.cargo/config.toml delete mode 100644 ebpf-demo/xdp_drop/Cargo.toml delete mode 100644 ebpf-demo/xdp_drop/src/lib.rs delete mode 100644 ebpf-demo/xdp_drop/src/main.rs delete mode 100644 ebpf-demo/xdp_pass_kern.c delete mode 100644 ebpf-demo/xdp_pass_kern.o create mode 100644 eclipta.yaml create mode 100644 examples/ebpf/Makefile create mode 100644 examples/ebpf/simple_trace.c create mode 100644 examples/ebpf/simple_xdp.c delete mode 100755 tests/ebpf_loader delete mode 100644 tests/loader.c delete mode 100644 tests/xdp_pass_kern.o diff --git a/.gitignore b/.gitignore index e34f02a..d5783a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,43 +1,96 @@ -# === Rust build & cargo files === +# Rust build artifacts /target/ -**/target/ +**/*.rs.bk +Cargo.lock -# === IDE/editor folders === -.idea/ +# IDE and editor files .vscode/ +.idea/ *.swp *.swo +*~ -# === OS generated files === +# OS generated files .DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db Thumbs.db -# === Logs, temp, runtime === +# Logs *.log +logs/ +/var/log/eclipta/ + +# Runtime data /run/eclipta/ -*.json +/var/lib/eclipta/ +/tmp/eclipta/ + +# Configuration files with sensitive data +config.yaml +*.key +*.pem +*.crt +*.p12 + +# eBPF compiled objects (keep source, ignore compiled) +*.o +*.so +*.skel.h + +# Keep sample eBPF objects for testing +!bin/simple_trace.o +!bin/simple_xdp.o + +# Database files +*.db +*.sqlite +*.sqlite3 -# === Byproducts === +# Backup files *.bak +*.backup *.old -# === Environment files === -.env -.env.* +# Temporary files +*.tmp +*.temp + +# Coverage reports +tarpaulin-report.html +lcov.info + +# Profiling data +*.prof +perf.data* -# === Rust/Cargo specific === -Cargo.lock # optional: keep it if you're building a binary (e.g., CLI), not a library -/.cargo/ +# Documentation build +/book/ +/docs/_build/ + +# Package files +*.tar.gz +*.zip +*.deb +*.rpm + +# Local development +.env +.env.local +.env.*.local -# === Coverage/test tools === -htmlcov/ +# Test artifacts +test-results/ coverage/ -*.lcov -# === Debug/profiler === -*.profraw -*.profdata -flamegraph.svg +# eBPF development +vmlinux.h +*.ll +*.bc -/tests/* -/bin/* \ No newline at end of file +# System files +/var/cache/eclipta/ +/var/run/eclipta.pid \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..da3dd78 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +# Changelog + +## [0.1.0] - 2025-01-27 + +### Added +- Complete project restructure for open source release +- Comprehensive documentation in `eclipta.yaml` +- Sample eBPF programs for testing +- Proper `.gitignore` configuration +- MIT License +- Updated installation script +- Clean project structure + +### Changed +- Removed unnecessary directories (`bin/`, `ebpf-demo/`, `tests/`, `target/`) +- Updated `Cargo.toml` workspace configuration +- Streamlined README.md +- Reorganized project layout + +### Removed +- Old binary files and demo programs +- Unnecessary test files +- Build artifacts and temporary files + +### Project Structure +``` +eclipta/ +├── eclipta-cli/ # Main CLI application +├── examples/ebpf/ # Sample eBPF programs +├── bin/ # Compiled eBPF programs for testing +├── eclipta.yaml # Comprehensive documentation +├── README.md # Project overview +├── LICENSE # MIT License +├── install.sh # Installation script +└── .gitignore # Git ignore rules +``` + +### Sample eBPF Programs +- `simple_trace.c` - Basic tracepoint program +- `simple_xdp.c` - Basic XDP program +- Compiled versions available in `bin/` directory + +### Documentation +- Complete command reference in `eclipta.yaml` +- Installation instructions +- Usage examples +- Development guidelines +- Troubleshooting guide diff --git a/Cargo.lock b/Cargo.lock index d927a08..f426006 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,22 +128,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "aya" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758d57288601ecc9d149e3413a5f23d6b72c0373febc97044d4f4aa149033b5e" -dependencies = [ - "bitflags 1.3.2", - "bytes", - "lazy_static", - "libc", - "log", - "object 0.28.4", - "parking_lot", - "thiserror", -] - [[package]] name = "aya" version = "0.13.1" @@ -638,7 +622,7 @@ name = "eclipta-cli" version = "1.0.0" dependencies = [ "anyhow", - "aya 0.13.1", + "aya", "byteorder", "bytes", "chrono", @@ -1377,25 +1361,6 @@ dependencies = [ "libm", ] -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.28.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" -dependencies = [ - "memchr", -] - [[package]] name = "object" version = "0.32.2" @@ -2312,7 +2277,6 @@ dependencies = [ "bytes", "libc", "mio 1.0.4", - "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -2513,16 +2477,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "user" -version = "0.1.0" -dependencies = [ - "anyhow", - "aya 0.11.0", - "num_cpus", - "tokio", -] - [[package]] name = "utf8_iter" version = "1.0.4" diff --git a/Cargo.toml b/Cargo.toml index a18ab6d..183e450 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ - "eclipta-cli", - "ebpf-demo/user" + "eclipta-cli" ] resolver = "2" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f30b677 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Mahesh Bhatiya + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index c6df465..95f80ae 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,182 @@ -# eclipta CLI — Self-Hosted Observability Platform +# Eclipta CLI -**eclipta** is a lightweight, modular CLI tool for managing, monitoring, and observing Linux agents across your infrastructure. Built in Rust, eclipta enables DevOps, sysadmins, and SREs to inspect system health, manage agent lifecycles, and capture real-time performance metrics — entirely self-hosted. +A lightweight, modular CLI tool for managing and monitoring eBPF programs on Linux systems. Built in Rust for performance and reliability. ## Features -- Agent lifecycle control (`load`, `unload`, `restart`, `kill`, `update`) -- Live system metrics (`cpu`, `memory`, `disk`, `network`, `processes`) -- Dynamic agent discovery (`/run/eclipta/*.json`) -- Snapshot syncing to `/etc/eclipta/agents/snapshot.json` -- Configuration management with safe JSON storage -- Realtime monitoring terminal UI (`monitor`, `live`) -- Alert handling and health summaries -- Zero external dependencies — Rust-native +- **eBPF Program Management**: Load, unload, and monitor eBPF programs +- **System Monitoring**: Real-time system metrics and process monitoring +- **Interactive TUI**: Terminal-based user interface for monitoring +- **Configuration Management**: Flexible configuration system +- **Network Monitoring**: Network interface and traffic monitoring +- **Database Integration**: SQLite-based data storage and management -## Installation +## Quick Start + +### Prerequisites + +- Rust 1.70+ +- Linux kernel 4.18+ with eBPF support +- libbpf development libraries +- clang and llvm for eBPF compilation + +### Installation -### Build from source: ```bash -git clone https://github.com/yourorg/eclipta.git -cd eclipta/cli +# Clone the repository +git clone https://github.com/stackroost/eclipta.git +cd eclipta + +# Build from source cargo build --release + +# Install (requires sudo for eBPF operations) sudo cp target/release/eclipta /usr/local/bin/eclipta ``` -## Usage +### Basic Usage ```bash -eclipta [options] -``` +# Show welcome message and help +eclipta welcome -### Common Commands: - -| Command | Description | -|-------------------|----------------------------------------------| -| `load` | Load/start an agent binary | -| `unload` | Gracefully unload agent | -| `restart-agent` | Restart agent process | -| `kill-agent` | Forcefully kill agent | -| `update-agent` | Replace agent binary with updated version | -| `monitor` | Interactive terminal UI of all agents | -| `live` | Stream real-time agent logs + stats | -| `logs` | View system or agent logs | -| `agent-logs` | Tail logs from a specific agent | -| `watch-cpu` | Monitor CPU usage of an agent | -| `alerts` | List all agents currently in alert state | -| `agents` | Show all detected agents | -| `inspect-agent` | Print detailed stats of a specific agent | -| `inspect` | Inspect eclipta CLI environment | -| `ping-all` | Check if all agents are alive/responding | -| `sync-agents` | Scan `/run/eclipta` and sync active agents | -| `config` | Get/set/list CLI configuration options | -| `version` | Show current CLI version | -| `welcome` | Show welcome message and setup hint | -| `status` | Show CLI runtime status | - -## Agent Snapshot Format - -Synced to: `/etc/eclipta/agents/snapshot.json` - -```json -[ - { - "id": "agent-001", - "hostname": "host1", - "version": "0.2.1", - "cpu_load": [0.39, 1.09, 1.38], - "mem_used_mb": 4865, - "disk_used_mb": 79177, - "net_rx_kb": 247187, - "alert": false, - "last_seen": "2025-07-01T16:38:29Z" - } -] +# Check system status +eclipta status + +# Load a sample eBPF program +eclipta load --program bin/simple_trace.o --name my-tracer + +# List loaded programs +eclipta list + +# Start interactive monitoring +eclipta monitor + +# Unload program +eclipta unload --program my-tracer ``` -## Development +## Sample eBPF Programs -To run locally: +The project includes sample eBPF programs for testing: + +- `bin/simple_trace.o` - Basic tracepoint program +- `bin/simple_xdp.o` - Basic XDP program + +To build your own eBPF programs: ```bash -cargo run -- monitor +cd examples/ebpf +make ``` -## Roadmap +## Commands -- [ ] `install-agent` from GitHub Releases -- [ ] Remote API mode (multi-node) -- [ ] TUI dashboard for snapshot view -- [ ] Plugin architecture for collectors +### System Commands +- `welcome` - Show welcome message and setup help +- `status` - Show CLI runtime status +- `monitor` - Interactive terminal UI for monitoring +- `logs` - View system or agent logs +- `watch-cpu` - Monitor CPU usage -## License +### eBPF Commands +- `load` - Load eBPF program +- `unload` - Unload eBPF program +- `list` - List loaded programs +- `inspect` - Inspect program details +- `upload` - Upload program to storage +- `remove` - Remove program from storage -MIT © 2025 Mahesh Bhatiya +### Network Commands +- `ping-all` - Check agent connectivity +- `alerts` - List alerting agents + +### Configuration Commands +- `config` - Manage configuration +- `daemon` - Start daemon process + +### Database Commands +- `check-db` - Check database status +- `migrate` - Run database migrations + +## Configuration + +Configuration is stored in `/etc/eclipta/config.yaml`. Key settings: + +```yaml +log_level: "info" +daemon_enabled: false +auto_start_programs: false +monitoring_interval: 5 +``` ## Project Structure ``` -/cli/ - src/ - commands/ - utils/ - main.rs # CLI parser & dispatch -/run/eclipta/ # Live agent metrics (.json) -/etc/eclipta/ # Persistent config + snapshot.json +eclipta/ +├── eclipta-cli/ # Main CLI application +│ ├── src/ +│ │ ├── commands/ # Command implementations +│ │ ├── utils/ # Utility functions +│ │ └── main.rs # Entry point +│ └── Cargo.toml +├── examples/ebpf/ # Sample eBPF programs +│ ├── simple_trace.c +│ ├── simple_xdp.c +│ └── Makefile +├── bin/ # Compiled eBPF programs +│ ├── simple_trace.o +│ └── simple_xdp.o +├── eclipta.yaml # Comprehensive documentation +└── README.md ``` +## Development + +### Building + +```bash +# Development build +cargo build + +# Release build +cargo build --release + +# Run tests +cargo test + +# Format code +cargo fmt + +# Lint code +cargo clippy +``` + +### Adding New Commands + +1. Create command module in `eclipta-cli/src/commands/` +2. Add command to `main.rs` command enum +3. Implement command handler +4. Update documentation in `eclipta.yaml` + +## Documentation + +For comprehensive documentation including all commands, options, and examples, see `eclipta.yaml`. + ## Contributing -PRs welcome! If you're building tooling for observability or Linux system automation, open an issue or suggest improvements. \ No newline at end of file +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Add tests if applicable +5. Submit a pull request + +## License + +MIT © 2025 Mahesh Bhatiya + +## Support + +- Issues: [GitHub Issues](https://github.com/stackroost/eclipta/issues) +- Documentation: [GitHub Wiki](https://github.com/stackroost/eclipta/wiki) +- Email: support@eclipta.dev \ No newline at end of file diff --git a/bin/ebpf.o b/bin/ebpf.o deleted file mode 100644 index 1c6457f921e5dd850dcbc8a26b957d97c762936e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2776 zcma)84NP0t6~6w#?*Zo75Zc<|*?GnUnJl3X^JmAVGk%0PZKOFr(pZxzHrNi?5@LhH zPg-p@2A-3;l@l=ub(v%mR<+YM(JGpl7F8Hi;!rDNQ8l5AF?;-kR3sq{n=&cdcCIPY zG;Pu@@0|1Q@xAAM=kHyt+~i_yF+vnVs8!0+!P|L1cjW(qA$(~GJl;9US9aMmi|m}7 z=!jw^XdXwY2LWnxlKLCdB+%y|jTE5)>^EJ*m$CX4x<}XBE zY9&prFtUd%H90hfjjS;&;Sf1VRB@JhPrwWoxC8&ip!WYVSXKxIe}+*F6rr*4V9VbD z*$+_}_;(2Wlz`kZWKopMo1F9xa?JK#uK2p*w%Az+`aEBN06)9uqmq?5$)gwnd?QA5 zTZoGe!apZ@2s}GI7o~g*(HkQ$hk{{=&MiHgk2T}hZxDSX@6!>zy}aK`TLAY?&e zBnRLKO(Jg3j1Iw!$(AC66b{>NC3q!5Vhdg&Mk47);|YWU@JE6ofE?&jf$+c;F+!hM zazLY3k4Tk;hoh0)@`E#C?sC6Qh(3nc+=bt&$pAf_p*_WdhA?LsNJOjwqOX_e8u3Y2 zk?fJ2+6++DQmc9@uDUx)d)S=pvQSA%)R5#FBBF*=Zv;Gki^Qek1=qcz?q1%@@XAyn zwH~E1tgM5TEp1R6cB)!FtyQ`Aw|z~z-&)|KLue{@SP)k-$-!p;|=O@n)=Hmwa$uKlcV(VD4ojk z1t&eLp{IkYS*PUpQO=m;j3Ze-kuVH%hOo#qoOl%uebI0FLS!0GNN=Cvy)AsFH{@?8 zdL6u9fpew2drbBi$-c5v%Ta2{BFiw;I(Wh8R10zSRHOQyhF%D&7t+u;sxJjhGy%o%EVUwHR0ZK%mBeHL4A#9e%tVVYXDQ_orLpVyuAR8Tdad1YOrTGgngH7dy9nr4@W`HATk*DxV6 z4u_1XmRpd0aP}hLwDCP&UitY0>Io~$q^XA%*~1u|k`RcxJ|w`GQzK9+IKuupNM&%K z(U?v^=o%nXDa&+BH9M+GH>wxow5P0%r7}3bGBC2ja+=Tu1<_^WPsRAR1F-kwVSzc4 zFb^jTbKHI?rxZj?YSX-Ab*cgC-MH##u-J3>G)p~UWKYtPCwAE;HU(cK$toku%z?8v zETQgp+`h`AJ0}t*sKYVNkb)SBjM0!eB{D-WhZ7O5V6{;_6I3laX=oeN#~@Sz@~Ya# zaAB!3*X2syVS*8{zPY)1N6;FJKAldIM(a@Ix+MUY$Q{^aKg2PI-QDi9ofo?NZA`bj zv+Ko{||-G8=^(Yf5!ZjZCx=wbA%zIGpLfTu!B3aa|$#nn>Il9H3v zNMAG(i_Fij-#>YOG5O{E?8(&p)ZNwQ-0<Y*TU5fYs1;K_-=2~qTL|SWt%r1 z$eTiWjgp+_5{*SDcv?}$~oRHk829X^YhYH@bWaQs*)Y@U;Z0xvXcTs;d-uS75lpL22B7xpA`E62A zBoBWpm}`q_UK>2E3(8Njv3?y{5RHpI?I)vimbdfnS^A|H}A65c{V~xk$mdJ9vetT^HjwSwoLR_=82V=)NEU`WadK`Z| z-`1nnXyQ{6;?K;)fbH?A+e$IWa%k2l= z=IsN1?tHgfUsZ|w6F2R?|L9d$b*-U>b$Xn&tV>^4RcolOb=5fy)pedKV_kh)Z9U5x zstg8atJmW`>jqxwa@W?nT5AlhnmT<|Yps4?+vy9HtiRLQ=JuXH)8T(L3ucRd4GBX= F{{-=VW^4ce diff --git a/bin/ebpf.so b/bin/ebpf.so deleted file mode 100644 index 6fe7192dd0e390d13977e6f3b05d025ed60b40b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1312 zcmbtTO-lk{5FWMK>d=R@AQEIzmmuv>=T@X3=ul{fPO01W0a}~8M$(}!{e=ENT{?F2 zxPPO+5d;|>Z03DuT3sZFURa-*XP)`k+1K06ovnB*26AHX0ih=>KsgcGmNG3cP-!NH zl;_RsxPiJZ9s`R|oniRuQshC0Q9q)r%SBCid5zILBQE)$efhzR*3WVNO2JTsnV44i z*Sge4<|Q-}qpFVdnOxKTf+dZU>l!cjHF_nDGXF4q^v!#ZVXA14zbig?WIgtM$9^eV zQqLhhQEmJoGy#QpTC9`3-lRJN>jh6r4m3|^K>fDQ2^)u{K9(BKq z_)vH1w%dZN?_B%jcn(6v^`LfEb*k<$arKKU2eJ*P<~J&~<6fMd`#H}(b&hhj+dOP~ zl@knme#5U+5nFY_!tVZIv6L?rx#2%y8}q~Mg~d9&B0Hp%75!xN9f{Nbx=?JfnTaIm z+aKz(Xb#FRbDr#5GNSp*7#PFH5&`2Y&!1tR=A-wN{3+&5L~0e?!4&7qyv(q>~w#Ke{_1 z8wK|yD585&4+^e(67-pZ>eZ{B zS69|oGnPdH7X3~`Nwh?>g&|*4Y>j5w^GmIMN7JV^*2$W*DwXM+T?u9;X3kV5&rIdR z8KTU?WLMUvAD=s4S}J8`iEPVSnKa_j>I7Ac;_23}yyk)`%((OsHjWyYG|U+6Qo!@o41`H1ZE%w(7GL%D3; z%I69rBg)a*&Qo!l4TS;~Ut~(TkzBS&3*aC!+|D@9xW!m!++%#1@ioRb7#nS`yH`H& zgRs@>mLFPl9&{e1u+{0eeK!ichVL|}+U#}wYR7B(VN;VZ>IHta(eCZ6W|wGW|9$>dt%IH0lfj#Rj{(mmswSe^`{WoHWZh3L(zb{~LMRHYyI+w9`2HXYkPR2z>0L}-U6bt7>%O-W_ zSVo8C9w0i!^n@YHk%d=E%8yk8KrG-{M%+7M3zqfg_!!@dx*5*I%vqJtw$5fw=kB&1 zLCE~iZ@wS==zaX|9jiZ7j@~Zu3g`?G-`OpqD?$@QoyFk6fM@_0h9u^ni2mryvO2HV*heapRs;2?rs&J z`kXoGdpsVX>;OD`Fogh+;d>SW17y6TWIWz1`UU_yWXUfw`VAnm%m$IsvjCCHN*c=Z zhP+_NvLAF4sx0{-13zU1;B2sSt1EyEdre8P9ddHNm@Beh*nsyk0N--*dfsJ@606iTuNeoWO58Pi(F_10i+_BOWfhyP+S262~fG+pVteDjDH= z*_|D>59L;Ow-*nxn@_LAtaIA!gO2O*LSbuf_&G={ip0qzyMfp7&9~?9&LXc)PI#%K zs6Jy{kpKDnE61beCQRXy7&0>GVsS9{v`85Ga6u0zp_UX9Jo+OE5eqkqm%fu2=}VD6 z*YV~VHnfA8&p3|CZR!xZspF3{6=M1}*W{C#ng2=FVNLO4R>6`k zH0()`{6ep>(Oy64F}a-dn~?dbmBGF AoB#j- literal 0 HcmV?d00001 diff --git a/bin/simple_xdp.o b/bin/simple_xdp.o new file mode 100644 index 0000000000000000000000000000000000000000..76087153641266178ee4e78fb31cb1e9ea7eed2d GIT binary patch literal 4568 zcmbtXZ){uD6+h3`cEIvA$T9FAl}_Z2 z*%@($ow2degge&QKD2%3*znGgo^U(N4v0H8J$ifQ*3@mO*bWibai&K_;@8Ra=uZ$o zu@?r1QYnZ%6jP}~5PRdWB7j>$B)K0myS9k*5ccPFwQ+`>05(c{}$@0fG6RE2*MRqce*vBc2jKg`zXLx3ehPdZ{37@Q_$~1J;E%w627e0v8~AhZC2$O7 zG7QdwOI5$Vlsy|X!pcfLd-Hhihq;3iR%)x&z*{S?=1P)ZUa1B7n!g-`%X$c#D~%vu zs;;!k`Jhy-tTz38u;$Y#%m)jri{e!)rJx=LQd;&K;&~Hua}#I0Q`7fMdBrocQ=TWS zdRSSi2jy&~-jvgmv);tvlXJzXNhMFtot#y|?8K>4N+_OI!`#&5^xV|Xi-NUzeyNE? zD{<8iLt&&+b4|*A(?`zMk8W0?7u3s~ygWh=HVp-KosCq4TQ2mKV$0Ctr8&8A6=JqDHZpwei^I&{ILG?;Q0yiLmmj9D$u zV;tA=I>y_z{2ay;U{ErSM^TC5P|ij&bEc6~d@y8HH59dtQ;GBgtg;WlAa$EyeKaSj zWpcg!VETOw2ALT0_XrR6Q3?Js8qwqEUp_$eQ)h&2R42p7_d1j4Xgdms$Ij#Daj9B> za8;F?@2LGOs1Y<c=mKm*{*pg6pf52RE~HK8B$Cp`*g$?}|&j`QEaG|pF@FtS0|txosHm^})1 zo!zl5iECXSvW)!cjj#VxJl1pkv7V#PWWPFBht9e9>vMO$^Xgr{{ng#;yI$G<#Xp-+ z#x4w9S`7~kl`^kC^zV^(_ttS!CiY#3V(eNB|tLoKd;axE?d~_KYNc=W%iqxyh~p)JWI}- z{UPRj0ZcNu{d{;Yne#F6_9*LUJ-q*~x9|-XzQw}FEIe=F2Q@bN`cslC2Metw&tF(* z1ZO4J4Az>GYXsHY;o_0p28fKpX2V-qTnvL|xcODk0WfD`;aUkig&9Z3FP9tiiDE~( zN_}xfa@FeDn&)F0zg;$eW(?Qvw%G7%LFeU^L$;>BAi41Vni};B=-2(;!@G#U znz88;KjI+%5^N{)?J+ujys2YPw^N}Vw8^ZOcB%nK83&CH_}++?!@!*hh9u zx_qXU%LHv?+p;ga<$qk~U)K)IPnA}0+!u$Tqsch9osO^(LHn$P2Aa`_jgggue$@1V zntQ~|*|xvLM7Q-1>H5uTN3Ngun7#hLLTAUM%kOpmo%%hfBiZ%z7wEd>AJ_TKIWa$f zzuWmU&~?jyo*zMwspAM;nV;X;Zutvc-k-f{=YI*hZu!5}`S+W|dNlq<{Q`t;`RBXj z=Whh#Z}#PB=(^?4>I>x$CXpU(+b5y#mVaI6U)6rxfBqV>^B;$fF~`B}^s>(XaJv$+ y$#2F-pmS#~uV7dQZ_rmdzbPN)CmFv8iF^pb*ccthaehQWS?$1qAJfjWMqH=MuzVU2p&w7fk6OC&;cy$z`zbvxgE%60^+G)F$MOxFvb=z_AW#Pkz*tPo40a2!UBh!3yVt#Msc(IiT@jTv&L(_@HpZrymxsF!dZT29#EU>PPoO08}2` zK6Lks0M#-3{Lcqc4Nxs$Y6p}9N-H1$^B=l?C!icm4Ok(Rh=9@wP#UBUqz>kO38**# Dw?8VZ diff --git a/ebpf-demo/Cargo.lock b/ebpf-demo/Cargo.lock deleted file mode 100644 index 227823c..0000000 --- a/ebpf-demo/Cargo.lock +++ /dev/null @@ -1,119 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aya-ebpf" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8dbaf5409a1a0982e5c9bdc0f499a55fe5ead39fe9c846012053faf0d404f73" -dependencies = [ - "aya-ebpf-bindings", - "aya-ebpf-cty", - "aya-ebpf-macros", - "rustversion", -] - -[[package]] -name = "aya-ebpf-bindings" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783dc1a82a3d71d83286165381dcc1b1d41643f4b110733d135547527c000a9a" -dependencies = [ - "aya-ebpf-cty", -] - -[[package]] -name = "aya-ebpf-cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cce099aaf3abb89f9a1f8594ffe07fa53738ebc2882fac624d10d9ba31a1b10" - -[[package]] -name = "aya-ebpf-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f47f7b4a75eb5f1d7ba0fb5628d247b1cf20388658899177875dabdda66865" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "simple-ebpf" -version = "0.1.0" -dependencies = [ - "aya-ebpf", -] - -[[package]] -name = "syn" -version = "2.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" diff --git a/ebpf-demo/Cargo.toml b/ebpf-demo/Cargo.toml deleted file mode 100644 index 82e0bfb..0000000 --- a/ebpf-demo/Cargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[workspace] -members = ["user", - "xdp_drop" -] -resolver = "2" diff --git a/ebpf-demo/user/Cargo.toml b/ebpf-demo/user/Cargo.toml deleted file mode 100644 index 52ad8dc..0000000 --- a/ebpf-demo/user/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "user" -version = "0.1.0" -edition = "2024" - -[dependencies] -aya = "0.11" -anyhow = "1" -tokio = { version = "1", features = ["full"] } -num_cpus = "1" \ No newline at end of file diff --git a/ebpf-demo/user/src/main.rs b/ebpf-demo/user/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/ebpf-demo/user/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/ebpf-demo/xdp_drop/.cargo/config.toml b/ebpf-demo/xdp_drop/.cargo/config.toml deleted file mode 100644 index c3ccdee..0000000 --- a/ebpf-demo/xdp_drop/.cargo/config.toml +++ /dev/null @@ -1,5 +0,0 @@ -[build] -target-dir = "target" - -[target.bpfel-unknown-none] -linker = "bpf-linker" \ No newline at end of file diff --git a/ebpf-demo/xdp_drop/Cargo.toml b/ebpf-demo/xdp_drop/Cargo.toml deleted file mode 100644 index 45e47da..0000000 --- a/ebpf-demo/xdp_drop/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "simple-ebpf" -version = "0.1.0" -edition = "2021" - -[dependencies] -aya-ebpf = "0.1" - -[lib] -name = "simple_ebpf" -path = "src/lib.rs" -crate-type = ["cdylib"] diff --git a/ebpf-demo/xdp_drop/src/lib.rs b/ebpf-demo/xdp_drop/src/lib.rs deleted file mode 100644 index f91c453..0000000 --- a/ebpf-demo/xdp_drop/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![no_std] -#![no_main] - -use aya_ebpf::{macros::xdp, programs::XdpContext}; -use aya_ebpf::bindings::xdp_action; - -#[xdp(name = "xdp_drop")] -pub fn xdp_drop(_ctx: XdpContext) -> u32 { - xdp_action::XDP_DROP -} - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/ebpf-demo/xdp_drop/src/main.rs b/ebpf-demo/xdp_drop/src/main.rs deleted file mode 100644 index fb47aa8..0000000 --- a/ebpf-demo/xdp_drop/src/main.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![no_std] -#![no_main] - -use aya_ebpf::{ - bindings::xdp_action, - macros::xdp, - programs::XdpContext, -}; - -#[xdp] -pub fn simple_ebpf_program(ctx: XdpContext) -> u32 { - match try_simple_ebpf_program(ctx) { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_ABORTED, - } -} - -fn try_simple_ebpf_program(_ctx: XdpContext) -> Result { - // Simple success - no logging to avoid macro issues - Ok(xdp_action::XDP_PASS) // Return 2 (XDP_PASS - allows packet through) -} - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - unsafe { core::hint::unreachable_unchecked() } -} \ No newline at end of file diff --git a/ebpf-demo/xdp_pass_kern.c b/ebpf-demo/xdp_pass_kern.c deleted file mode 100644 index 6446b16..0000000 --- a/ebpf-demo/xdp_pass_kern.c +++ /dev/null @@ -1,12 +0,0 @@ -// xdp_pass_kern.c -#include -#include - -// XDP program: just passes all packets without dropping -SEC("xdp") -int xdp_pass(struct xdp_md *ctx) { - return XDP_PASS; // let packets continue -} - -// Required license declaration -char LICENSE[] SEC("license") = "GPL"; diff --git a/ebpf-demo/xdp_pass_kern.o b/ebpf-demo/xdp_pass_kern.o deleted file mode 100644 index 0a95580acb7b3e3af7bcc1725ba3aac160e682d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 720 zcmb<-^>JfjWMqH=MuzVU2p&w7fk6OC&;cy$z`zbvxgE%60^+G)F$MOxFvb=z_AW#Pkz*tPo40a2!UBh!3yVt#Msc(IiT@jTv&L(_@HpZrymxsF!dZT29#EU>PPoO08}2` zK6Lks0M#-3{Lcqc4Nxs$Y6p}9N-H1$^B=l?C!icm4Ok(Rh=9@wP#UBUqz>kO38**# Dw?8VZ diff --git a/eclipta-cli/src/commands/ebpf/load.rs b/eclipta-cli/src/commands/ebpf/load.rs index d77b1c6..e9366b1 100644 --- a/eclipta-cli/src/commands/ebpf/load.rs +++ b/eclipta-cli/src/commands/ebpf/load.rs @@ -49,6 +49,8 @@ pub struct ProgramRequirements { pub requires_interface: bool, pub requires_socket_fd: bool, pub program_type: String, + pub tracepoint_category: Option, + pub tracepoint_name: Option, } pub async fn handle_load(opts: LoadOptions) -> Result<()> { @@ -137,6 +139,8 @@ pub fn validate_ebpf_file(path: &PathBuf) -> Result { let mut requires_interface = false; let mut requires_socket_fd = false; let mut program_type = String::new(); + let mut tracepoint_category: Option = None; + let mut tracepoint_name: Option = None; for section in obj.sections() { println!("Section: {}", section.name().unwrap()); @@ -144,6 +148,13 @@ pub fn validate_ebpf_file(path: &PathBuf) -> Result { if name.starts_with("tracepoint/") { found_sections.insert("Tracepoint".to_string()); program_type = "Tracepoint".to_string(); + + // Extract category and name from tracepoint section + let parts: Vec<&str> = name.split('/').collect(); + if parts.len() >= 3 { + tracepoint_category = Some(parts[1].to_string()); + tracepoint_name = Some(parts[2].to_string()); + } } else { match name { XDP_SECTION | XDP_DROP_SECTION => { @@ -196,6 +207,8 @@ pub fn validate_ebpf_file(path: &PathBuf) -> Result { requires_interface, requires_socket_fd, program_type, + tracepoint_category, + tracepoint_name, }) } @@ -318,6 +331,30 @@ async fn attach_program_to_kernel( Err(anyhow!("No SocketFilter program found in eBPF object")) } + "Tracepoint" => { + let category = requirements.tracepoint_category.as_ref() + .ok_or_else(|| anyhow!("Tracepoint category not found in ELF sections"))?; + let name = requirements.tracepoint_name.as_ref() + .ok_or_else(|| anyhow!("Tracepoint name not found in ELF sections"))?; + + let mut ebpf = Ebpf::load_file(path) + .context("Failed to load eBPF for Tracepoint attachment")?; + + for (prog_name, program) in ebpf.programs_mut() { + if let Program::TracePoint(tp_prog) = program { + tp_prog.load() + .context("Failed to load Tracepoint program")?; + + tp_prog.attach(category, name) + .context(format!("Failed to attach Tracepoint program to '{}:{}'", category, name))?; + + println!("Tracepoint program '{}' attached to '{}:{}'", prog_name, category, name); + return Ok(format!("Tracepoint program attached to {}:{}", category, name)); + } + } + Err(anyhow!("No Tracepoint program found in eBPF object")) + } + _ => { println!("Program type '{}' not yet implemented for kernel attachment", requirements.program_type); Ok(format!("Program type {} loaded but not attached", requirements.program_type)) @@ -378,6 +415,47 @@ async fn verify_kernel_attachment(requirements: &ProgramRequirements, opts: &Loa println!("SocketFilter verification requires manual inspection of socket state"); } + "Tracepoint" => { + let category = requirements.tracepoint_category.as_ref() + .ok_or_else(|| anyhow!("Tracepoint category not found for verification"))?; + let name = requirements.tracepoint_name.as_ref() + .ok_or_else(|| anyhow!("Tracepoint name not found for verification"))?; + + // Use bpftool to verify tracepoint attachment + let output = Command::new("bpftool") + .args(["link", "list"]) + .output() + .await + .context("Failed to execute bpftool command")?; + + let output_str = String::from_utf8_lossy(&output.stdout); + + // Look for tracepoint programs in the output + let mut found = false; + for line in output_str.lines() { + if line.contains("tracepoint") { + println!(" Found tracepoint link: {}", line.trim()); + // Check if this line contains our specific tracepoint + if line.contains(category) && line.contains(name) { + found = true; + break; + } + } + } + + if found { + println!("Tracepoint program verified as attached to '{}:{}'", category, name); + } else { + println!("Tracepoint program not found attached to '{}:{}'", category, name); + println!("Available tracepoint links:"); + for line in output_str.lines() { + if line.contains("tracepoint") { + println!(" {}", line.trim()); + } + } + } + } + _ => { println!("Verification not implemented for program type '{}'", requirements.program_type); } @@ -404,6 +482,13 @@ fn print_program_summary( println!(" Socket FD: {}", socket_fd); } + if let Some(ref category) = requirements.tracepoint_category { + println!(" Tracepoint Category: {}", category); + } + if let Some(ref name) = requirements.tracepoint_name { + println!(" Tracepoint Name: {}", name); + } + println!(" Interface Required: {}", requirements.requires_interface); println!(" Socket FD Required: {}", requirements.requires_socket_fd); println!(" Kernel Attachment: {}", attach_result); @@ -477,6 +562,11 @@ pub fn get_program_requirements(sections: &HashSet) -> ProgramRequiremen requires_socket_fd = true; program_type = "SocketFilter".to_string(); } + "Tracepoint" => { + program_type = "Tracepoint".to_string(); + // Note: For this function, we can't extract category/name from section names + // as we only have the processed section names, not the raw ELF section names + } _ => {} } } @@ -486,6 +576,8 @@ pub fn get_program_requirements(sections: &HashSet) -> ProgramRequiremen requires_interface, requires_socket_fd, program_type, + tracepoint_category: None, + tracepoint_name: None, } } diff --git a/eclipta.yaml b/eclipta.yaml new file mode 100644 index 0000000..bbd49ae --- /dev/null +++ b/eclipta.yaml @@ -0,0 +1,353 @@ +# Eclipta CLI - Self-Hosted Observability Platform +# Comprehensive project documentation and configuration + +project: + name: "eclipta" + version: "0.1.0" + description: "Lightweight, modular CLI tool for managing, monitoring, and observing Linux agents" + author: "Mahesh Bhatiya" + license: "MIT" + repository: "https://github.com/stackroost/eclipta" + homepage: "https://github.com/stackroost/eclipta" + +# Build and Development Configuration +build: + rust_version: "1.70+" + target: "x86_64-unknown-linux-gnu" + features: + - "default" + - "release" + profile: + release: + strip: true + opt-level: "z" + lto: true + codegen-units: 1 + +# Dependencies +dependencies: + runtime: + - "libbpf" + - "clang" + - "llvm" + development: + - "cargo" + - "rustc" + - "clippy" + - "rustfmt" + +# CLI Commands Documentation +commands: + system: + welcome: + description: "Show welcome message and setup hint" + usage: "eclipta welcome" + examples: + - "eclipta welcome" + + status: + description: "Show CLI runtime status" + usage: "eclipta status [options]" + options: + - "--verbose, -v: Show detailed status information" + - "--json: Output in JSON format" + examples: + - "eclipta status" + - "eclipta status --verbose" + - "eclipta status --json" + + monitor: + description: "Interactive terminal UI of all agents" + usage: "eclipta monitor" + examples: + - "eclipta monitor" + + logs: + description: "View system or agent logs" + usage: "eclipta logs [options]" + options: + - "--agent, -a: Show logs for specific agent" + - "--follow, -f: Follow log output" + - "--lines, -n: Number of lines to show" + examples: + - "eclipta logs" + - "eclipta logs --agent my-agent" + - "eclipta logs --follow --lines 100" + + watch_cpu: + description: "Monitor CPU usage of an agent" + usage: "eclipta watch-cpu [options]" + options: + - "--agent, -a: Agent to monitor (required)" + - "--interval, -i: Update interval in seconds" + examples: + - "eclipta watch-cpu --agent my-agent" + - "eclipta watch-cpu --agent my-agent --interval 2" + + ebpf: + load: + description: "Load/start an eBPF program" + usage: "eclipta load [options]" + options: + - "--program, -p: Path to eBPF program file (required)" + - "--name, -n: Name for the loaded program" + - "--interface, -i: Network interface (for XDP programs)" + examples: + - "eclipta load --program bin/simple_trace.o" + - "eclipta load --program bin/simple_xdp.o --interface eth0" + - "eclipta load --program bin/simple_trace.o --name my-tracer" + + unload: + description: "Gracefully unload eBPF program" + usage: "eclipta unload [options]" + options: + - "--program, -p: Program name or ID to unload (required)" + - "--force, -f: Force unload without graceful shutdown" + examples: + - "eclipta unload --program my-tracer" + - "eclipta unload --program 12345 --force" + + list: + description: "List all loaded eBPF programs" + usage: "eclipta list" + examples: + - "eclipta list" + + inspect: + description: "Inspect eBPF program details" + usage: "eclipta inspect [options]" + options: + - "--program, -p: Program name or ID to inspect (required)" + - "--maps: Show program maps" + - "--functions: Show program functions" + examples: + - "eclipta inspect --program my-tracer" + - "eclipta inspect --program my-tracer --maps" + + upload: + description: "Upload eBPF program to remote storage" + usage: "eclipta upload [options]" + options: + - "--program, -p: Path to eBPF program file (required)" + - "--name, -n: Name for the uploaded program" + - "--description, -d: Description of the program" + examples: + - "eclipta upload --program bin/simple_trace.o --name trace-open" + + remove: + description: "Remove eBPF program from storage" + usage: "eclipta remove [options]" + options: + - "--program, -p: Program name or ID to remove (required)" + - "--force, -f: Force removal without confirmation" + examples: + - "eclipta remove --program trace-open" + - "eclipta remove --program 12345 --force" + + network: + ping_all: + description: "Check if all agents are alive/responding" + usage: "eclipta ping-all" + examples: + - "eclipta ping-all" + + alerts: + description: "List all agents currently in alert state" + usage: "eclipta alerts" + examples: + - "eclipta alerts" + + config: + config: + description: "Get/set/list CLI configuration options" + usage: "eclipta config [options]" + options: + - "--get, -g: Get configuration value" + - "--set, -s: Set configuration value" + - "--list, -l: List all configuration options" + - "--key, -k: Configuration key" + - "--value, -v: Configuration value" + examples: + - "eclipta config --list" + - "eclipta config --get --key log_level" + - "eclipta config --set --key log_level --value debug" + + daemon: + description: "Start eclipta daemon process" + usage: "eclipta daemon" + examples: + - "eclipta daemon" + + store: + check_db: + description: "Check database connectivity and status" + usage: "eclipta check-db [options]" + options: + - "--verbose, -v: Show detailed database information" + examples: + - "eclipta check-db" + - "eclipta check-db --verbose" + + migrate: + description: "Run database migrations" + usage: "eclipta migrate [options]" + options: + - "--up: Run pending migrations" + - "--down: Rollback last migration" + - "--status: Show migration status" + examples: + - "eclipta migrate --up" + - "eclipta migrate --status" + + other: + version: + description: "Show current CLI version" + usage: "eclipta version [options]" + options: + - "--verbose, -v: Show detailed version information" + examples: + - "eclipta version" + - "eclipta version --verbose" + + run: + description: "Run a command or script" + usage: "eclipta run [options]" + options: + - "--command, -c: Command to run (required)" + - "--timeout, -t: Command timeout in seconds" + examples: + - "eclipta run --command 'ls -la'" + - "eclipta run --command 'ping google.com' --timeout 10" + +# File Structure +file_structure: + root: + - "Cargo.toml: Workspace configuration" + - "README.md: Project documentation" + - "eclipta.yaml: This configuration file" + - "install.sh: Installation script" + + eclipta_cli: + - "src/main.rs: CLI entry point and command dispatch" + - "src/commands/: Command implementations" + - "system/: System monitoring commands" + - "ebpf/: eBPF program management commands" + - "network/: Network-related commands" + - "config/: Configuration management commands" + - "store/: Database and storage commands" + - "src/utils/: Utility functions" + - "src/db/: Database management" + + examples: + - "ebpf/: Sample eBPF programs" + - "simple_trace.c: Basic tracepoint program" + - "simple_xdp.c: Basic XDP program" + - "Makefile: Build configuration" + + bin: + - "simple_trace.o: Compiled tracepoint program" + - "simple_xdp.o: Compiled XDP program" + +# Installation Instructions +installation: + prerequisites: + - "Rust 1.70 or later" + - "libbpf development libraries" + - "clang and llvm for eBPF compilation" + - "Linux kernel 4.18+ with eBPF support" + + build_from_source: + - "git clone https://github.com/stackroost/eclipta.git" + - "cd eclipta" + - "cargo build --release" + - "sudo cp target/release/eclipta /usr/local/bin/eclipta" + + install_dependencies: + ubuntu_debian: + - "sudo apt update" + - "sudo apt install libbpf-dev clang llvm" + arch_linux: + - "sudo pacman -S libbpf clang llvm" + fedora: + - "sudo dnf install libbpf-devel clang llvm" + +# Usage Examples +usage_examples: + basic_monitoring: + - "eclipta welcome" + - "eclipta status" + - "eclipta monitor" + + ebpf_program_management: + - "eclipta load --program bin/simple_trace.o --name my-tracer" + - "eclipta list" + - "eclipta inspect --program my-tracer" + - "eclipta unload --program my-tracer" + + system_monitoring: + - "eclipta logs --follow" + - "eclipta watch-cpu --agent my-agent" + - "eclipta alerts" + - "eclipta ping-all" + +# Configuration +configuration: + config_file: "/etc/eclipta/config.yaml" + data_directory: "/var/lib/eclipta" + log_directory: "/var/log/eclipta" + runtime_directory: "/run/eclipta" + + default_settings: + log_level: "info" + daemon_enabled: false + auto_start_programs: false + monitoring_interval: 5 + +# Troubleshooting +troubleshooting: + common_issues: + - "Permission denied: Run with sudo for eBPF operations" + - "eBPF program load failed: Check kernel version and eBPF support" + - "libbpf not found: Install libbpf development package" + - "Compilation errors: Ensure clang and llvm are installed" + + debugging: + - "Use --verbose flag for detailed output" + - "Check logs in /var/log/eclipta/" + - "Verify eBPF program with: eclipta inspect --program " + - "Test with simple programs first" + +# Contributing +contributing: + development_setup: + - "Fork the repository" + - "Clone your fork" + - "Create a feature branch" + - "Make your changes" + - "Add tests if applicable" + - "Submit a pull request" + + coding_standards: + - "Follow Rust formatting with rustfmt" + - "Run clippy for linting" + - "Add documentation for public APIs" + - "Write meaningful commit messages" + + testing: + - "Unit tests: cargo test" + - "Integration tests: cargo test --test integration" + - "eBPF programs: Test with sample programs in examples/" + +# License and Legal +license: + type: "MIT" + year: "2025" + holder: "Mahesh Bhatiya" + text: "See LICENSE file for full license text" + +# Support and Community +support: + issues: "https://github.com/stackroost/eclipta/issues" + discussions: "https://github.com/stackroost/eclipta/discussions" + documentation: "https://github.com/stackroost/eclipta/wiki" + email: "support@eclipta.dev" diff --git a/examples/ebpf/Makefile b/examples/ebpf/Makefile new file mode 100644 index 0000000..82a0a26 --- /dev/null +++ b/examples/ebpf/Makefile @@ -0,0 +1,33 @@ +# Makefile for eBPF examples +# Requires: clang, llvm, libbpf + +CLANG ?= clang +LLC ?= llc +ARCH ?= x86 + +# Common flags +CFLAGS := -O2 -g -Wall -Wno-unused-value -Wno-pointer-sign \ + -Wno-compare-distinct-pointer-types \ + -Werror -Wno-unused-function -Wno-unused-variable + +# Include paths +INCLUDES := -I/usr/include/bpf -I/usr/include/linux + +# Target files +TARGETS := simple_trace.o simple_xdp.o + +.PHONY: all clean + +all: $(TARGETS) + +%.o: %.c + $(CLANG) $(CFLAGS) $(INCLUDES) -target bpf -c $< -o $@ + +clean: + rm -f *.o + +install: all + mkdir -p ../../bin + cp *.o ../../bin/ + +.PHONY: install diff --git a/examples/ebpf/simple_trace.c b/examples/ebpf/simple_trace.c new file mode 100644 index 0000000..c3cbbe5 --- /dev/null +++ b/examples/ebpf/simple_trace.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +// Simple eBPF program for testing + +#include +#include + +// Simple program that always returns 0 +SEC("tracepoint/syscalls/sys_enter_open") +int trace_open(void *ctx) +{ + return 0; +} + +char _license[] SEC("license") = "GPL"; diff --git a/examples/ebpf/simple_xdp.c b/examples/ebpf/simple_xdp.c new file mode 100644 index 0000000..43549a5 --- /dev/null +++ b/examples/ebpf/simple_xdp.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +// Simple XDP eBPF program for testing + +#include +#include + +// Simple XDP program that passes all packets +SEC("xdp") +int xdp_pass(struct xdp_md *ctx) +{ + return XDP_PASS; +} + +char _license[] SEC("license") = "GPL"; diff --git a/install.sh b/install.sh index 2856d6e..34c74db 100755 --- a/install.sh +++ b/install.sh @@ -2,37 +2,91 @@ set -euo pipefail -echo "Building Eclipta..." - -# Step 1: Build Frontend (Vite) -echo "Building frontend..." -cd frontend -npm install -npm run build -cd .. - -# Step 2: Build Backend -echo "Building backend..." -cargo build --release --package backend - -# Step 3: Package -DIST_DIR="dist" -echo "Packaging into $DIST_DIR/" -rm -rf "$DIST_DIR" -mkdir -p "$DIST_DIR" - -cp target/release/backend "$DIST_DIR/eclipta-backend" -cp -r frontend/dist/* "$DIST_DIR/" - -# Step 4: Optional CLI build -if [ -f "eclipta-cli/Cargo.toml" ]; then - echo "🛠 Building CLI..." - cargo build --release --package eclipta-cli - cp target/release/eclipta-cli "$DIST_DIR/eclipta-cli" +echo "Installing Eclipta CLI..." + +# Check if Rust is installed +if ! command -v cargo &> /dev/null; then + echo "Error: Rust/Cargo is not installed. Please install Rust first." + echo "Visit: https://rustup.rs/" + exit 1 +fi + +# Check if required dependencies are available +echo "Checking dependencies..." + +# Check for libbpf +if ! pkg-config --exists libbpf; then + echo "Warning: libbpf not found. You may need to install libbpf development libraries." + echo "Ubuntu/Debian: sudo apt install libbpf-dev" + echo "Arch Linux: sudo pacman -S libbpf" + echo "Fedora: sudo dnf install libbpf-devel" +fi + +# Check for clang +if ! command -v clang &> /dev/null; then + echo "Warning: clang not found. You may need clang for eBPF compilation." + echo "Ubuntu/Debian: sudo apt install clang llvm" + echo "Arch Linux: sudo pacman -S clang llvm" + echo "Fedora: sudo dnf install clang llvm" +fi + +# Build the CLI +echo "Building Eclipta CLI..." +cargo build --release + +# Create installation directory +INSTALL_DIR="/usr/local/bin" +echo "Installing to $INSTALL_DIR..." + +# Copy binary (requires sudo) +if [ -w "$INSTALL_DIR" ]; then + cp target/release/eclipta-cli "$INSTALL_DIR/eclipta" + chmod +x "$INSTALL_DIR/eclipta" else - echo "CLI not found, skipping." + echo "Installing with sudo..." + sudo cp target/release/eclipta-cli "$INSTALL_DIR/eclipta" + sudo chmod +x "$INSTALL_DIR/eclipta" +fi + +# Create configuration directory +CONFIG_DIR="/etc/eclipta" +if [ ! -d "$CONFIG_DIR" ]; then + echo "Creating configuration directory..." + if [ -w "/etc" ]; then + mkdir -p "$CONFIG_DIR" + else + sudo mkdir -p "$CONFIG_DIR" + fi +fi + +# Create runtime directory +RUNTIME_DIR="/run/eclipta" +if [ ! -d "$RUNTIME_DIR" ]; then + echo "Creating runtime directory..." + if [ -w "/run" ]; then + mkdir -p "$RUNTIME_DIR" + else + sudo mkdir -p "$RUNTIME_DIR" + fi fi +# Build sample eBPF programs +echo "Building sample eBPF programs..." +cd examples/ebpf +make install +cd ../.. + +echo "" +echo " Installation complete!" +echo "" +echo "Usage:" +echo " eclipta welcome # Show welcome message" +echo " eclipta status # Check system status" +echo " eclipta load --help # Load eBPF program" +echo " eclipta monitor # Start monitoring" +echo "" +echo "Sample eBPF programs are available in bin/:" +echo " bin/simple_trace.o # Basic tracepoint program" +echo " bin/simple_xdp.o # Basic XDP program" echo "" -echo "Build complete!" -echo "Run backend with: ./dist/eclipta-backend" +echo "For full documentation, see eclipta.yaml" diff --git a/tests/ebpf_loader b/tests/ebpf_loader deleted file mode 100755 index 8ce3ed881b5ec5bb6b38d6bf721a79b27e1c6333..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32560 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 diff --git a/tests/loader.c b/tests/loader.c deleted file mode 100644 index 83fe66e..0000000 --- a/tests/loader.c +++ /dev/null @@ -1,237 +0,0 @@ -// loader.c -// Build: -// gcc -O2 -g loader.c -o ebpf_loader -lbpf -lelf -lz -// -// Run examples: -// sudo ./ebpf_loader /path/to/program.o -// sudo ./ebpf_loader --iface eth0 /path/to/xdp_prog.o -// sudo ./ebpf_loader -i eth0 /path/to/xdp_prog.o -// -// This loader: -// - auto-detects eBPF program sections (xdp, kprobe, tracepoint, uprobe, tc) -// - loads the object into kernel (verifier) -// - attaches programs according to detected section type -// - keeps links alive until SIGINT/SIGTERM - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static struct bpf_object *g_obj = NULL; -static struct bpf_link **g_links = NULL; -static int g_link_count = 0; -static int g_alloc_links = 0; -static const char *g_iface = NULL; - -static void usage(const char *prog) { - fprintf(stderr, - "Usage: %s [--iface IFACE] \n" - "Options:\n" - " -i, --iface IFACE Interface to attach XDP programs to (eg eth0)\n" - " -h, --help Show this help\n\n" - "Examples:\n" - " sudo %s ./xdp_pass_kern.o --iface eth0\n" - " sudo %s ./trace_prog.o\n", - prog, prog, prog); -} - -static int starts_with(const char *s, const char *pref) { - if (!s || !pref) return 0; - return strncmp(s, pref, strlen(pref)) == 0; -} - -static void free_links_and_obj(void) { - if (g_links) { - for (int i = 0; i < g_link_count; ++i) { - if (g_links[i]) { - bpf_link__destroy(g_links[i]); - g_links[i] = NULL; - } - } - free(g_links); - g_links = NULL; - } - if (g_obj) { - bpf_object__close(g_obj); - g_obj = NULL; - } - g_link_count = 0; - g_alloc_links = 0; -} - -static void handle_sigint(int sig) { - (void)sig; - fprintf(stderr, "\nReceived signal, cleaning up and detaching...\n"); - free_links_and_obj(); - exit(0); -} - -int main(int argc, char **argv) { - const char *path = NULL; - - // parse options with getopt_long - static struct option long_options[] = { - {"iface", required_argument, 0, 'i'}, - {"help", no_argument, 0, 'h'}, - {0,0,0,0} - }; - - int opt; - int option_index = 0; - while ((opt = getopt_long(argc, argv, "i:h", long_options, &option_index)) != -1) { - switch (opt) { - case 'i': - g_iface = optarg; - break; - case 'h': - default: - usage(argv[0]); - return 0; - } - } - - if (optind < argc) { - path = argv[optind]; - } - - if (!path) { - fprintf(stderr, "Error: missing path to .o file\n"); - usage(argv[0]); - return 1; - } - - // register signal handlers for graceful shutdown - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = handle_sigint; - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - - struct bpf_object *obj = NULL; - struct bpf_program *prog; - struct bpf_link *link = NULL; - int err; - - obj = bpf_object__open_file(path, NULL); - if (!obj) { - fprintf(stderr, "failed to open BPF object '%s'\n", path); - return 1; - } - g_obj = obj; // for cleanup on signal - - printf("Detected program sections in %s:\n", path); - bpf_object__for_each_program(prog, obj) { - const char *sec = bpf_program__section_name(prog); - printf(" - section: %s\n", sec ? sec : "(null)"); - } - - err = bpf_object__load(obj); - if (err) { - fprintf(stderr, "failed to load BPF object: %s\n", strerror(-err)); - bpf_object__close(obj); - g_obj = NULL; - return 1; - } - - // allocate link array sized to #programs - int prog_count = 0; - bpf_object__for_each_program(prog, obj) prog_count++; - if (prog_count > 0) { - g_links = calloc(prog_count, sizeof(*g_links)); - if (!g_links) { - fprintf(stderr, "failed to allocate link array\n"); - bpf_object__close(obj); - g_obj = NULL; - return 1; - } - g_alloc_links = prog_count; - } - - // Attach programs based on section prefix - bpf_object__for_each_program(prog, obj) { - const char *sec = bpf_program__section_name(prog); - if (!sec) sec = ""; - - // Get program fd (should be valid after load) - int prog_fd = bpf_program__fd(prog); - if (prog_fd < 0) { - fprintf(stderr, "warning: failed to get fd for program section %s\n", sec); - continue; - } - - if (starts_with(sec, "xdp")) { - if (!g_iface) { - printf("XDP program found (section=%s) but no --iface provided. Skipping attachment.\n", sec); - continue; - } - int ifindex = if_nametoindex(g_iface); - if (ifindex == 0) { - fprintf(stderr, "invalid interface name '%s'\n", g_iface); - continue; - } - - int flags = 0; // change if you want SKB mode: XDP_FLAGS_SKB_MODE - err = bpf_set_link_xdp_fd(ifindex, prog_fd, flags); - if (err < 0) { - fprintf(stderr, "failed to attach XDP program to %s: %s\n", g_iface, strerror(-err)); - } else { - printf("Attached XDP program (section=%s) to iface %s (ifindex=%d)\n", sec, g_iface, ifindex); - // Note: bpf_set_link_xdp_fd does not return a bpf_link object; record placeholder NULL - // so cleanup loop knows this was attached via link-less attach (we cannot bpf_link__destroy it). - // If you prefer to use libbpf's xdp attach helpers (returning bpf_link), swap to that API. - // We'll still keep a placeholder in g_links to maintain indexing. - if (g_link_count < g_alloc_links) g_links[g_link_count++] = NULL; - } - } else if (starts_with(sec, "kprobe") || starts_with(sec, "kretprobe") || - starts_with(sec, "tracepoint") || starts_with(sec, "uprobe") || - starts_with(sec, "uretprobe")) { - link = bpf_program__attach(prog); - if (!link) { - fprintf(stderr, "failed to attach program section %s via libbpf\n", sec); - } else { - printf("Attached program section %s via libbpf (link=%p)\n", sec, (void*)link); - if (g_link_count < g_alloc_links) g_links[g_link_count++] = link; - else { - // shouldn't happen but handle gracefully - bpf_link__destroy(link); - } - } - } else if (starts_with(sec, "tc") || starts_with(sec, "clsact") || starts_with(sec, "classifier")) { - fprintf(stdout, "TC-like section detected (%s). TC attach not implemented by this loader.\n", sec); - // Optionally implement TC attach logic using rtnetlink or libbpf's helper if available. - } else { - // Generic fallback: try libbpf attach - link = bpf_program__attach(prog); - if (!link) { - fprintf(stderr, "fallback attach failed for section %s\n", sec); - } else { - printf("Fallback attached section %s (link=%p)\n", sec, (void*)link); - if (g_link_count < g_alloc_links) g_links[g_link_count++] = link; - else bpf_link__destroy(link); - } - } - } - - printf("All attachments attempted. Active links stored: %d\n", g_link_count); - printf("Loader will keep running to hold programs attached. Press Ctrl-C to exit and detach.\n"); - - // Keep process alive until SIGINT/SIGTERM - while (1) { - pause(); // signal handler will cleanup - } - - // unreachable, kept for completeness - free_links_and_obj(); - return 0; -} diff --git a/tests/xdp_pass_kern.o b/tests/xdp_pass_kern.o deleted file mode 100644 index 0a95580acb7b3e3af7bcc1725ba3aac160e682d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 720 zcmb<-^>JfjWMqH=MuzVU2p&w7fk6OC&;cy$z`zbvxgE%60^+G)F$MOxFvb=z_AW#Pkz*tPo40a2!UBh!3yVt#Msc(IiT@jTv&L(_@HpZrymxsF!dZT29#EU>PPoO08}2` zK6Lks0M#-3{Lcqc4Nxs$Y6p}9N-H1$^B=l?C!icm4Ok(Rh=9@wP#UBUqz>kO38**# Dw?8VZ