{"id":37205347,"url":"https://github.com/sufield/e5s","last_synced_at":"2026-01-14T23:39:42.196Z","repository":{"id":322178781,"uuid":"1084407613","full_name":"sufield/e5s","owner":"sufield","description":"Identity based authentication library based on go-spiffe SDK. Replace API keys with  cryptographic identity  and reduce the attack surface that comes with leaked credentials, secret sprawl, and rotation headaches","archived":false,"fork":false,"pushed_at":"2025-11-17T21:47:06.000Z","size":69955,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-17T23:26:24.779Z","etag":null,"topics":["go","golang","spiffe","spire"],"latest_commit_sha":null,"homepage":"","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/sufield.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/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":"2025-10-27T16:31:25.000Z","updated_at":"2025-11-17T21:47:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sufield/e5s","commit_stats":null,"previous_names":["sufield/e5s"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sufield/e5s","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufield%2Fe5s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufield%2Fe5s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufield%2Fe5s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufield%2Fe5s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sufield","download_url":"https://codeload.github.com/sufield/e5s/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufield%2Fe5s/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28439305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T22:37:52.437Z","status":"ssl_error","status_checked_at":"2026-01-14T22:37:31.496Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["go","golang","spiffe","spire"],"created_at":"2026-01-14T23:39:41.439Z","updated_at":"2026-01-14T23:39:42.177Z","avatar_url":"https://github.com/sufield.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# e5s - Identity Based Authentication Library\n\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/11425/badge)](https://www.bestpractices.dev/projects/11425)\n[![Go Report Card](https://goreportcard.com/badge/github.com/sufield/e5s)](https://goreportcard.com/report/github.com/sufield/e5s)\n\nA Go library for building applications that use identity-based authentication instead of API keys.\n\nBuild mutual TLS services with SPIFFE identity verification and automatic certificate rotation with almost no boilerplate code. Built on the battle-tested go-spiffe SDK.\n\nEliminate API keys and plaintext secrets from your services, dramatically reducing the attack surface that comes with leaked credentials, secret sprawl, and rotation headaches.\n\n# The Problem\n\n## ❌ Before: Static API Keys\n\nEvery service call required a shared secret.\n\n**Weather Server**\n\n```go\nfunc (s *WeatherServer) GetForecast(w http.ResponseWriter, r *http.Request) {\n    apiKey := r.Header.Get(\"Authorization\")\n    if apiKey != \"Bearer weather-client-secret\" {\n        http.Error(w, \"unauthorized\", http.StatusUnauthorized)\n        return\n    }\n\n    // business logic\n    forecast := s.GetData()\n    json.NewEncoder(w).Encode(forecast)\n}\n```\n\n**Weather Client**\n\n```go\nfunc main() {\n    apiKey := os.Getenv(\"WEATHER_API_KEY\")\n    req, _ := http.NewRequest(\"GET\", \"https://weather-service:8080/forecast\", nil)\n    req.Header.Set(\"Authorization\", \"Bearer \"+apiKey)\n\n    resp, err := http.DefaultClient.Do(req)\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer resp.Body.Close()\n}\n```\n\n**Problems**\n\n* Secrets in code or environment variables\n* Manual rotation and redeployment when keys change\n* Leaks through logs, git, or config files\n* Separate keys for every service pair\n\n---\n\n# The Solution\n\n## ✅ After: Identity-Based Authentication with e5s\n\nEach service has its own **cryptographic identity** (SPIFFE ID).\nNo API keys, no secrets, no manual rotation.\n\n**Weather Server**\n\n```go\nfunc forecastHandler(w http.ResponseWriter, r *http.Request) {\n    // Client already authenticated via mTLS\n    forecast := map[string]string{\"forecast\": \"Sunny\"}\n    json.NewEncoder(w).Encode(forecast)\n}\n\nfunc main() {\n    http.HandleFunc(\"/forecast\", forecastHandler)\n\n    if err := e5s.Serve(\"server-config.yaml\", http.DefaultServeMux); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n**server-config.yaml:**\n```yaml\nversion: 1\nspire:\n  workload_socket: \"unix:///tmp/spire-agent/public/api.sock\"\nserver:\n  listen_addr: \":8080\"\n  allowed_client_spiffe_id: \"spiffe://prod.company.com/weather-client\"\n```\n\n**Weather Client**\n\n```go\nfunc main() {\n    client, cleanup, err := e5s.Client(\"client-config.yaml\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer cleanup()\n\n    resp, err := client.Get(\"https://weather-service:8080/forecast\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer resp.Body.Close()\n\n    var result map[string]string\n    json.NewDecoder(resp.Body).Decode(\u0026result)\n    fmt.Println(result[\"forecast\"])\n}\n```\n\n**client-config.yaml:**\n\n```yaml\nversion: 1\nspire:\n  workload_socket: \"unix:///tmp/spire-agent/public/api.sock\"\nclient:\n  expected_server_spiffe_id: \"spiffe://prod.company.com/weather-service\"\n```\n\n---\n\n## What Changed\n\n| Aspect         | Before (API Keys)       | After (e5s)               |\n| -------------- | ----------------------- | ------------------------- |\n| Authentication | Shared secret in header | mTLS using SPIFFE IDs     |\n| Rotation       | Manual                  | Automatic                 |\n| Secret Storage | Env vars / config       | None                      |\n| Breach Risk    | High (key leaks)        | Low (certs rotate hourly) |\n| Setup          | Add key per service     | Register identity once    |\n| Maintenance    | Continuous              | Zero-touch                |\n\n---\n\n## Example Setup\n\n```bash\n# One-time identity registration\nspire-server entry create -spiffeID spiffe://prod.company.com/weather-client \\\n    -parentID spiffe://prod.company.com/spire-agent -selector unix:uid:1000\n\nspire-server entry create -spiffeID spiffe://prod.company.com/weather-service \\\n    -parentID spiffe://prod.company.com/spire-agent -selector unix:uid:1000\n```\n\nNow, your services prove who they are through short-lived certificates—no shared keys, no dashboards, no secret rotation scripts.\n\n## How does e5s work?\n\ne5s solves the challenges of implementing secure, identity-based mutual TLS (mTLS) in distributed systems by adopting the proven SPIFFE standard. It simplifies \n\n- SPIFFE-based authentication\n- Automates certificate rotation without downtime\n- Enforces peer ID verification\n- Minimizes manual certificate management\n\nIdeal for microservices in zero-trust environments. It reduces security risks from expired certs or weak auth, while offering high-level APIs for ease and low-level controls for customization.\n\n## Why Not Use go-spiffe SDK Directly?\n\nUsing e5s over the go-spiffe SDK directly offers these advantages for developers building mTLS services:\n\n- **Simpler Abstraction**: The high-level API (e.g., `e5s.Run()`) handles configuration, SPIRE connections, certificate rotation, and verification with minimal code—often one line—versus manual SDK setup and boilerplate.\n- **Config-Driven**: YAML-based config (`e5s.dev.yaml` for dev, `e5s.prod.yaml` for prod) streamlines setup for servers/clients, including timeouts and trust domains, without custom coding.\n- **Built-in Features**: Automatic zero-downtime rotation, policy-based SPIFFE ID verification, TLS 1.3 enforcement, graceful shutdown, health checks, structured logging and thread-safety are ready out-of-the-box.\n- **Low-Level Flexibility**: Direct access to pkg/spiffehttp and pkg/spire for customization, minimizing dependencies (core uses stdlib only).\n- **Ease of Adoption**: Comprehensive docs, quickstarts, and examples reduce integration time compared to raw SDK usage.\n\nUse go-spiffe directly only if you need non-HTTP services or custom workflows.\n\n## Features\n\n- **Simple High-Level API** - Config-driven with `e5s.Start()` and `e5s.Client()`\n- **Low-Level Control** - Direct access to `pkg/spiffehttp` and `pkg/spire` for custom use cases\n- **SDK-Based Implementation** - Uses official go-spiffe SDK API\n- **SPIRE Adapter** - Production-ready SPIRE Workload API implementation\n- **Automatic Rotation** - Zero-downtime certificate and trust bundle updates\n- **SPIFFE ID Verification** - Policy-based peer authentication\n- **TLS 1.3 Enforcement** - Strong cipher suites and security defaults\n- **Thread-Safe** - Share sources across multiple servers and clients\n- **Minimal Dependencies** \n    - Core (`pkg/spiffehttp`): stdlib only. \n    - SPIRE adapter (`pkg/spire`): `go-spiffe/v2`. \n    - High-level API (`e5s.go`): adds `yaml.v3`.\n    - Examples add `chi` (see `go.mod` for details)\n\n## Documentation\n\n- **[docs/](docs/)** - Documentation Table of Contents\n- **[Examples](examples/)** - Working code for all use cases\n\n## Quick Start\n\n### Installation\n\n```bash\ngo get github.com/sufield/e5s@latest\n```\n\n## Two Ways to Use e5s\n\nA **high-level** and a **low-level** APIs are provided because they serve different developer roles and abstraction levels:\n\n### High-Level API (`e5s.Start`, `e5s.Client`)\n\n**For:** Application developers\n**Use Case:** Secure HTTP services quickly\n**Goal:** Make identity-based mTLS work with one line of code\n\n- Handles configuration, SPIRE connection, certificate rotation, and verification internally\n- Reads `e5s.dev.yaml` (default) or specify via `-config` flag or `E5S_CONFIG` env var\n- Ideal when you just want secure communication without caring how certificates or trust domains are wired\n- Example use: web apps, microservices, APIs\n\n`examples/highlevel/`** - Start here for application development (production behavior, minimal code)\n\n**Benefits:** Zero boilerplate, hard to misuse, easy to run locally and in production with the same config\n\n### Low-Level API (`pkg/spiffehttp`, `pkg/spire`)\n\n**For:** Platform/Infra Engineer\n**Use Case:** Build custom SPIRE integrations or non-HTTP services\n**Goal:** Allow full control over mTLS internals\n\n- Build custom TLS configs and integrate with the go-spiffe SDK directly\n- Exposes `spiffehttp.NewServerTLSConfig` and `spire.NewIdentitySource`\n- Ideal for customizing certificate rotation intervals, trust domain logic, or integrating into non-HTTP systems\n\n**Benefits:** Extensible for advanced use cases, can plug in custom identity providers, useful for testing/debugging or building frameworks\n\n**`examples/minikube-lowlevel/`** - Platform/infrastructure example (full SPIRE + mTLS stack in Kubernetes)\n\n### 1. High-Level API\n\n#### Recommended for Most Users\n\nSimple configuration approach - create `e5s.yaml` with your SPIRE socket path and authorization policy.\n\n**Example Server:**\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"net/http\"\n\n    \"github.com/sufield/e5s\"\n)\n\nfunc main() {\n    http.HandleFunc(\"/hello\", func(w http.ResponseWriter, r *http.Request) {\n        id, ok := e5s.PeerID(r)\n        if !ok {\n            http.Error(w, \"unauthorized\", http.StatusUnauthorized)\n            return\n        }\n        fmt.Fprintf(w, \"Hello, %s!\\n\", id)\n    })\n\n    // Start mTLS server - handles config, SPIRE, and graceful shutdown\n    if err := e5s.Serve(\"e5s.yaml\", http.DefaultServeMux); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n**Example Client:**\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"io\"\n    \"log\"\n\n    \"github.com/sufield/e5s\"\n)\n\nfunc main() {\n    // Create mTLS HTTP client\n    client, cleanup, err := e5s.Client(\"e5s.yaml\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer func() {\n        if err := cleanup(); err != nil {\n            log.Printf(\"Cleanup error: %v\", err)\n        }\n    }()\n\n    // Perform mTLS GET request\n    resp, err := client.Get(\"https://localhost:8443/hello\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}\n```\n\n**Config File:**\n\nThe e5s library requires explicit configuration and never assumes a default environment.\n\n**Config files live in YOUR application codebase, not in the e5s library.**\n\nCopy the example config from `examples/highlevel/e5s.yaml` to your project and customize it:\n\nIn your application directory:\n\n```bash\ncp path/to/e5s/examples/highlevel/e5s.yaml ./e5s.yaml\n```\n\nThen edit for your environment (e5s.dev.yaml, e5s.prod.yaml, etc.)\n\nThen provide the config path:\n\n**Simple approach - blocks with signal handling:**\n```go\nif err := e5s.Serve(\"e5s.yaml\", handler); err != nil {\n    log.Fatal(err)\n}\n```\n\n**Advanced approach - custom shutdown:**\n```go\nshutdown, err := e5s.Start(\"e5s.yaml\", handler)\nif err != nil {\n    log.Fatal(err)\n}\ndefer shutdown()\n\n// Your custom shutdown logic here\n```\n\n**Example config structure:**\n\nSee the complete annotated config file: **[examples/highlevel/e5s.yaml](examples/highlevel/e5s.yaml)**\n\nThis single file contains both server and client configuration with detailed comments explaining each option.\n\nIn your application, create separate config files (`e5s.dev.yaml`, `e5s.staging.yaml`, `e5s.prod.yaml`) with environment-specific values for socket paths, trust domains, and timeouts. These files are part of your application codebase, not the e5s library.\n\n**For advanced usage** like environment variables, context timeouts, retry logic, and structured logging → See [examples/highlevel/ADVANCED.md](examples/highlevel/ADVANCED.md)\n\n**For a production-ready example** → See [examples/highlevel/](examples/highlevel/) for a server with chi router, graceful shutdown, health checks, and structured logging.\n\n### 2. Low-Level API\n\n#### For Advanced Use Cases\n\nThe low-level API provides programmatic control over TLS configuration when you need customization beyond what the high-level API offers.\n\n**Use the low-level API when:**\n- Building libraries or frameworks on top of e5s\n- Integrating with custom identity providers\n- Need fine-grained control over TLS settings\n- Building non-HTTP services\n\n**Core packages:**\n\n```go\nimport (\n    \"github.com/sufield/e5s/spire\"       // SPIRE Workload API client\n    \"github.com/sufield/e5s/spiffehttp\"  // mTLS TLS config builders\n)\n```\n\n**Basic Use:**\n\n1. Create SPIRE identity source: `spire.NewIdentitySource(ctx, config)`\n2. Build TLS config: `spiffehttp.NewServerTLSConfig()` or `spiffehttp.NewClientTLSConfig()`\n3. Create `http.Server` or `http.Client` with the TLS config\n4. Handle graceful shutdown manually\n\n**Comparison to high-level API:**\n\n| What | High-Level | Low-Level |\n|------|-----------|-----------|\n| Config | YAML file | Go code |\n| Setup code | ~10 lines | ~75+ lines |\n| Shutdown | Automatic | Manual |\n| Hardcoded values | None | Ports, IDs, domains in code |\n\n**Examples:**\n\n- **API reference:** [docs/reference/api.md](docs/reference/api.md)\n- **Working code:** [examples/middleware/](examples/middleware/)\n- **Infrastructure setup:** [examples/minikube-lowlevel/](examples/minikube-lowlevel/)\n\n## Architecture\n\n```\ne5s.go                  # High-level config-driven API\n├── e5s.Start()         # Server with config file\n├── e5s.Client()        # Client with config file\n└── e5s.PeerID()        # Extract authenticated peer\n\npkg/\n├── spiffehttp/        # Core mTLS library (provider-agnostic)\n│   ├── client.go       # Client TLS config builder\n│   ├── server.go       # Server TLS config builder\n│   ├── peer.go         # SPIFFE ID extraction/validation\n│   └── context.go      # Context helpers for peer info\n└── spire/              # SPIRE Workload API adapter\n    └── source.go       # SPIRE Workload API client\n\ninternal/config/        # Config file loading (not exported)\n├── config.go           # Config structs\n├── load.go             # YAML loader\n└── validate.go         # Config validation\n```\n\n**Two Levels:**\n\n1. **High-level** (`e5s.go`) - Config-driven, minimal code, works with any HTTP framework\n2. **Low-level** (`pkg/spiffehttp` + `pkg/spire`) - Full control over TLS, rotation, verification\n\n**Clear separation:**\n\n- `pkg/spiffehttp` - TLS configuration using go-spiffe SDK (no SPIRE dependency)\n- `pkg/spire` - SPIRE Workload API client\n- `e5s.go` - Wires everything together based on config file\n\nThe examples are separate modules (each has its own `go.mod`) so you can vendor/copy them without pulling extra dependencies into your service. The core library has minimal dependencies.\n\n## Development\n\n```bash\n# Run all CI checks locally before pushing\nmake ci\n\n# Individual checks\nmake lint          # Run golangci-lint (what CI runs)\nmake vet           # Run go vet\nmake fmt           # Format code\nmake test          # Run tests\nmake build         # Build example binaries\n```\n\n### Common Tasks\n\n```bash\n# Testing\nmake test                  # Run tests quickly\nmake test-race             # Run with race detector (recommended before push)\nmake test-coverage         # Generate coverage report\nmake test-coverage-html    # Open coverage in browser\n\n# Code Quality\nmake lint                  # Lint code (matches CI)\nmake lint-fix              # Auto-fix linting issues\nmake fmt                   # Format all code\nmake fmt-check             # Check if code is formatted\nmake vet                   # Run go vet\nmake tidy                  # Tidy go modules\nmake verify                # Verify go modules\n\n# Building\nmake build                 # Build examples/basic-server and examples/basic-client\nmake examples              # Build all examples (4 binaries)\nmake example-highlevel-server   # Application developer example\nmake example-highlevel-client\nmake example-minikube-server    # Platform/infra example\nmake example-minikube-client\n\n# Security\nmake sec-all               # Run all security checks\nmake sec-deps              # Check for vulnerabilities\nmake sec-lint              # Security-focused static analysis\n\n# All available targets\nmake help\n```\n\n## Security\n\ne5s implements defense-in-depth security with multiple layers:\n\n- **Static Analysis**: gosec, golangci-lint, govulncheck, gitleaks\n- **Container Security**: Pinned digests, non-root users, minimal images\n- **mTLS Enforcement**: TLS 1.3, SPIFFE identity verification, certificate rotation\n- **Runtime Monitoring**: Optional Falco integration for threat detection\n- **Supply Chain**: Signed releases with Cosign/Sigstore\n\n**For detailed security information:**\n\n- [Report Security Issues](https://github.com/sufield/e5s/security/advisories/new) - Private vulnerability disclosure\n- [Security Policy](.github/SECURITY.md) - Vulnerability disclosure policy\n\n**Run security scans:**\n\n```bash\nmake sec-all  # Run all security checks\n```\n\n## License\n\nMIT License - See [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsufield%2Fe5s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsufield%2Fe5s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsufield%2Fe5s/lists"}