From bc41c9c4d96615ba7eedd69cf92b1211bb4eac0d Mon Sep 17 00:00:00 2001 From: Adrian Martin Garcia Date: Mon, 20 Apr 2026 12:50:03 +0200 Subject: [PATCH 1/2] chore: instructions and context7 --- context7.json | 21 +++++ docs/integrations.md | 213 +++++++++++++++++++++++++++++++++++++++++++ docs/mods.md | 122 +++++++++++++++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 context7.json create mode 100644 docs/integrations.md create mode 100644 docs/mods.md diff --git a/context7.json b/context7.json new file mode 100644 index 0000000..3f21aa2 --- /dev/null +++ b/context7.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://context7.com/schema/context7.json", + "url": "https://context7.com/devops-ia/powerpipe", + "projectTitle": "Powerpipe Docker Image", + "description": "Community Docker image for Powerpipe — dashboards and compliance benchmarks for DevOps. Visualize cloud configurations and assess security posture against CIS, NIST, SOC 2, and other compliance frameworks. Multi-arch (amd64/arm64), production-ready.", + "folders": ["docs", "examples"], + "excludeFolders": ["scripts", ".github", "tests", "openspec"], + "excludeFiles": ["CONTRIBUTING.md", "structure-tests.yaml", "trivy.yaml", "cli-snapshot.json"], + "rules": [ + "Always set POWERPIPE_DATABASE to a valid Steampipe connection string (postgresql://steampipe:@:9193/steampipe) — Powerpipe cannot start without it", + "Always use --listen network flag (or POWERPIPE_LISTEN=network) to accept connections from outside the container", + "Powerpipe serves dashboards on port 9033 (not 9193 — that is Steampipe's PostgreSQL port)", + "The container runs as UID 9193 (GID 0) — ensure mounted volumes have correct ownership with chown -R 9193:0", + "Mount the mod workspace as a named volume at /workspace to persist installed mods across container restarts", + "Use depends_on with healthcheck condition when composing Steampipe + Powerpipe to ensure Steampipe is ready before Powerpipe starts", + "Install mods with docker exec powerpipe powerpipe mod install after the container is running", + "Use POWERPIPE_BASE_URL when running behind a reverse proxy or when sharing dashboard links externally", + "Prefer ghcr.io/devops-ia/powerpipe over devopsiaci/powerpipe (Docker Hub mirror) for GitHub Actions workflows", + "Run one-shot benchmarks without starting the server: powerpipe benchmark run --output brief" + ] +} diff --git a/docs/integrations.md b/docs/integrations.md new file mode 100644 index 0000000..351c677 --- /dev/null +++ b/docs/integrations.md @@ -0,0 +1,213 @@ +# Integrations + +Powerpipe serves an HTTP dashboard on port 9033. It works with any tool that can embed or proxy HTTP. + +## Steampipe + Powerpipe (Docker Compose) + +The standard full-stack setup pairs Powerpipe with Steampipe as the data source: + +```yaml +# docker-compose.yml +services: + steampipe: + image: ghcr.io/devops-ia/steampipe:2.4.1 + container_name: steampipe + command: ["steampipe", "service", "start", "--foreground", "--database-listen", "network"] + ports: + - "9193:9193" + environment: + STEAMPIPE_DATABASE_PASSWORD: steampipe + volumes: + - steampipe-data:/home/steampipe/.steampipe + - ./aws.spc:/home/steampipe/.steampipe/config/aws.spc:ro + healthcheck: + test: ["CMD", "pg_isready", "-h", "localhost", "-p", "9193", "-U", "steampipe"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + + powerpipe: + image: ghcr.io/devops-ia/powerpipe:1.5.1 + container_name: powerpipe + command: ["powerpipe", "server", "--listen", "network"] + ports: + - "9033:9033" + environment: + POWERPIPE_DATABASE: "postgresql://steampipe:steampipe@steampipe:9193/steampipe" + volumes: + - powerpipe-workspace:/workspace + depends_on: + steampipe: + condition: service_healthy + +volumes: + steampipe-data: + powerpipe-workspace: +``` + +```bash +docker compose up -d +open http://localhost:9033 +``` + +## Reverse proxy (nginx) + +Expose Powerpipe dashboards under a custom path or domain: + +```nginx +# nginx.conf +server { + listen 80; + server_name dashboards.example.com; + + location / { + proxy_pass http://powerpipe:9033; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +Set `POWERPIPE_BASE_URL` so that share links use the public URL: + +```yaml +services: + powerpipe: + image: ghcr.io/devops-ia/powerpipe:1.5.1 + environment: + POWERPIPE_DATABASE: "postgresql://steampipe:steampipe@steampipe:9193/steampipe" + POWERPIPE_BASE_URL: "https://dashboards.example.com" +``` + +Full compose with nginx: + +```yaml +# docker-compose-nginx.yml +services: + steampipe: + image: ghcr.io/devops-ia/steampipe:2.4.1 + command: ["steampipe", "service", "start", "--foreground", "--database-listen", "network"] + environment: + STEAMPIPE_DATABASE_PASSWORD: steampipe + volumes: + - steampipe-data:/home/steampipe/.steampipe + healthcheck: + test: ["CMD", "pg_isready", "-h", "localhost", "-p", "9193", "-U", "steampipe"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + + powerpipe: + image: ghcr.io/devops-ia/powerpipe:1.5.1 + environment: + POWERPIPE_DATABASE: "postgresql://steampipe:steampipe@steampipe:9193/steampipe" + POWERPIPE_BASE_URL: "https://dashboards.example.com" + volumes: + - powerpipe-workspace:/workspace + depends_on: + steampipe: + condition: service_healthy + + nginx: + image: nginx:alpine + ports: + - "80:80" + volumes: + - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - powerpipe + +volumes: + steampipe-data: + powerpipe-workspace: +``` + +## Grafana + +Embed Powerpipe dashboards in Grafana using the [Text panel](https://grafana.com/docs/grafana/latest/panels-visualizations/visualizations/text/) with an iframe, or use the [Infinity datasource](https://grafana.com/grafana/plugins/yesoreyeram-infinity-datasource/) to query benchmark JSON exports. + +### Iframe embed + +In a Grafana Text panel (HTML mode): + +```html + +``` + +> **Note:** Grafana must have `security.allow_embedding = true` in `grafana.ini`, and Powerpipe must be reachable from the Grafana container. + +### Compose with Grafana + +```yaml +# docker-compose-grafana.yml +services: + steampipe: + image: ghcr.io/devops-ia/steampipe:2.4.1 + command: ["steampipe", "service", "start", "--foreground", "--database-listen", "network"] + environment: + STEAMPIPE_DATABASE_PASSWORD: steampipe + volumes: + - steampipe-data:/home/steampipe/.steampipe + healthcheck: + test: ["CMD", "pg_isready", "-h", "localhost", "-p", "9193", "-U", "steampipe"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + + powerpipe: + image: ghcr.io/devops-ia/powerpipe:1.5.1 + environment: + POWERPIPE_DATABASE: "postgresql://steampipe:steampipe@steampipe:9193/steampipe" + volumes: + - powerpipe-workspace:/workspace + depends_on: + steampipe: + condition: service_healthy + + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + environment: + GF_SECURITY_ALLOW_EMBEDDING: "true" + volumes: + - grafana-data:/var/lib/grafana + +volumes: + steampipe-data: + powerpipe-workspace: + grafana-data: +``` + +## CI/CD — benchmark exports + +Export benchmark results as JSON for integration with CI pipelines or reporting tools: + +```bash +# GitHub Actions — run compliance check on schedule +docker run --rm \ + -v "$HOME/.aws:/home/powerpipe/.aws:ro" \ + -v "$PWD/workspace:/workspace" \ + -e POWERPIPE_DATABASE="${STEAMPIPE_CONNECTION_STRING}" \ + ghcr.io/devops-ia/powerpipe:1.5.1 \ + powerpipe benchmark run aws_compliance.benchmark.cis_aws_foundations_benchmark_v300 \ + --export /workspace/results.json \ + --output brief +``` + +Parse the JSON output with standard tools: + +```bash +# Count failed controls +jq '[.groups[].controls[] | select(.status == "alarm")] | length' workspace/results.json +``` diff --git a/docs/mods.md b/docs/mods.md new file mode 100644 index 0000000..6e992ef --- /dev/null +++ b/docs/mods.md @@ -0,0 +1,122 @@ +# Mods + +Powerpipe mods are collections of dashboards, benchmarks, and controls that run against your Steampipe data. Find mods at [hub.powerpipe.io](https://hub.powerpipe.io). + +## Managing mods + +```bash +# Install a mod +docker exec powerpipe powerpipe mod install github.com/turbot/steampipe-mod-aws-compliance + +# Install multiple mods +docker exec powerpipe sh -c " + powerpipe mod install github.com/turbot/steampipe-mod-aws-compliance && + powerpipe mod install github.com/turbot/steampipe-mod-kubernetes-compliance +" + +# List installed mods +docker exec powerpipe powerpipe mod list +# Output: +# NAME VERSION PATH +# github.com/turbot/steampipe-mod-aws-compliance v0.85.0 /workspace/.powerpipe/mods/... + +# Update a mod to the latest version +docker exec powerpipe powerpipe mod update github.com/turbot/steampipe-mod-aws-compliance + +# Update all mods +docker exec powerpipe powerpipe mod update + +# Remove a mod +docker exec powerpipe powerpipe mod uninstall github.com/turbot/steampipe-mod-aws-compliance +``` + +## Persisting mods across restarts + +Mods are installed inside the container at `/workspace`. Mount a named volume to persist them: + +```yaml +services: + powerpipe: + image: ghcr.io/devops-ia/powerpipe:1.5.1 + volumes: + - powerpipe-workspace:/workspace + +volumes: + powerpipe-workspace: +``` + +Without a persistent volume, mods are lost when the container is removed. + +## Popular mods + +| Mod | Description | Install | +|-----|-------------|---------| +| [aws-compliance](https://hub.powerpipe.io/mods/turbot/aws_compliance) | CIS, NIST, SOC 2, PCI DSS for AWS | `powerpipe mod install github.com/turbot/steampipe-mod-aws-compliance` | +| [aws-thrifty](https://hub.powerpipe.io/mods/turbot/aws_thrifty) | AWS cost optimization checks | `powerpipe mod install github.com/turbot/steampipe-mod-aws-thrifty` | +| [azure-compliance](https://hub.powerpipe.io/mods/turbot/azure_compliance) | CIS, NIST benchmarks for Azure | `powerpipe mod install github.com/turbot/steampipe-mod-azure-compliance` | +| [gcp-compliance](https://hub.powerpipe.io/mods/turbot/gcp_compliance) | CIS, NIST benchmarks for GCP | `powerpipe mod install github.com/turbot/steampipe-mod-gcp-compliance` | +| [kubernetes-compliance](https://hub.powerpipe.io/mods/turbot/kubernetes_compliance) | NSA/CISA, CIS benchmarks for K8s | `powerpipe mod install github.com/turbot/steampipe-mod-kubernetes-compliance` | + +## Mod workspace structure + +After installation, mods live under `/workspace/.powerpipe/mods/`: + +``` +/workspace/ +├── .powerpipe/ +│ └── mods/ +│ └── github.com/ +│ └── turbot/ +│ └── steampipe-mod-aws-compliance@v0.85.0/ +│ ├── mod.pp +│ ├── benchmarks/ +│ └── controls/ +└── mod.pp # your workspace mod file (optional) +``` + +## Running benchmarks from a mod + +```bash +# List all benchmarks in installed mods +docker exec powerpipe powerpipe benchmark list + +# Run a specific benchmark +docker exec powerpipe \ + powerpipe benchmark run aws_compliance.benchmark.cis_aws_foundations_benchmark_v300 + +# Run and export results +docker exec powerpipe \ + powerpipe benchmark run aws_compliance.benchmark.cis_aws_foundations_benchmark_v300 \ + --export /workspace/results.json \ + --output brief + +# Run a one-shot benchmark (no server) +docker run --rm \ + -v "$HOME/.aws:/home/powerpipe/.aws:ro" \ + -v "$PWD/workspace:/workspace" \ + -e POWERPIPE_DATABASE="postgresql://steampipe:pass@host.docker.internal:9193/steampipe" \ + ghcr.io/devops-ia/powerpipe:1.5.1 \ + powerpipe benchmark run aws_compliance.benchmark.cis_aws_foundations_benchmark_v300 \ + --output brief +``` + +## Creating a custom mod + +Mount a local directory with your own `mod.pp` and controls: + +```bash +# workspace/mod.pp +mod "local_checks" { + title = "My Custom Checks" +} +``` + +```yaml +services: + powerpipe: + image: ghcr.io/devops-ia/powerpipe:1.5.1 + volumes: + - ./workspace:/workspace + environment: + POWERPIPE_DATABASE: "postgresql://steampipe:pass@steampipe:9193/steampipe" +``` From 825ca5f8ce0a71fdf630c67fa1d9ff201dfb8fc3 Mon Sep 17 00:00:00 2001 From: Adrian Martin Garcia Date: Mon, 20 Apr 2026 12:52:25 +0200 Subject: [PATCH 2/2] chore: instructions and context7 --- .github/copilot-instructions.md | 70 +++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 3c681be..8a8d9cb 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -50,6 +50,9 @@ package.json → semantic-release config (do not modify) # Build docker build -t powerpipe:test . +# Build for a specific version +docker build --build-arg POWERPIPE_VERSION=1.5.1 -t powerpipe:test . + # Smoke test docker run --rm powerpipe:test powerpipe --version @@ -60,6 +63,73 @@ curl -sf http://localhost:9033/ && echo "OK" docker stop pp-test ``` +### Unit tests (no Docker required) + +```bash +pip install -r tests/requirements.txt + +# Full suite with coverage +python3 -m pytest tests/ --cov=compare_snapshots --cov-report=term-missing + +# Single test +python3 -m pytest tests/test_compare_snapshots.py::TestDiffLists::test_added_items -v +``` + +### Lint the Dockerfile + +```bash +docker run --rm -i hadolint/hadolint < Dockerfile +``` + +### Container structure tests (requires built image) + +```bash +docker run --rm \ + -v "$PWD/structure-tests.yaml:/structure-tests.yaml:ro" \ + -v /var/run/docker.sock:/var/run/docker.sock \ + gcr.io/gcp-runtimes/container-structure-test:latest \ + test --image powerpipe:test --config /structure-tests.yaml +``` + +### Security scan + +```bash +docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + aquasec/trivy image --severity CRITICAL --ignore-unfixed powerpipe:test +``` + +## Commit Message Format + +This repo uses [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat: add support for multi-arch builds +fix: correct workspace directory permissions +chore: bump powerpipe to 1.6.0 +docs: add mod installation example +``` + +| Type | When to use | +|------|------------| +| `feat` | New feature or capability | +| `fix` | Bug fix | +| `chore` | Maintenance (version bumps, CI tweaks) | +| `docs` | Documentation only | +| `refactor` | Code restructure without behaviour change | + +## Key Conventions + +- **Port 9033** is Powerpipe's HTTP port. Port 9193 belongs to Steampipe — don't confuse them. +- **UID 9193 / GID 0** — deliberate for OpenShift restricted SCC compatibility, consistent with the Steampipe image. +- **`git` is a required runtime dep** — `powerpipe mod install` fetches mods from GitHub repos at runtime. +- **Mods, not plugins** — Powerpipe uses *mods* (`powerpipe mod install`). "Plugins" is Steampipe terminology. +- **`POWERPIPE_DATABASE` is deprecated** — the preferred approach is connection config files, not this env var. +- **`ARG TARGETARCH`** is populated automatically by Docker Buildx for multi-arch builds (`linux/amd64`, `linux/arm64`). Do not hardcode it. +- **Unit tests import from `scripts/`** — `tests/conftest.py` prepends `scripts/` to `sys.path`, enabling `import compare_snapshots` without an installable package. +- **`behavior-check` CI job only runs on PRs when `POWERPIPE_VERSION` changes** in the Dockerfile. It extracts a fresh CLI snapshot, diffs it against `cli-snapshot.json`, and posts the result as a PR comment mentioning `@copilot`. +- **`structure-tests.yaml`** validates all ENV vars set in the Dockerfile plus binary presence, metadata labels, exposed port, and default CMD. When adding/removing `ENV` lines in the Dockerfile, update this file too. + ## Documentation Format Flag tables use this format: