container security

Scanning Kubernetes Manifests with Kubesec

Perform security risk analysis on Kubernetes resource manifests using Kubesec to identify misconfigurations, privilege escalation risks, and deviations from security best practices.

ci-cddevsecopskuberneteskubesecmanifest-scanningmisconfigurationsecurity-scanningstatic-analysis
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Kubesec is an open-source security risk analysis tool developed by ControlPlane that inspects Kubernetes resource manifests for common exploitable risks such as privilege escalation, writable host mounts, and excessive capabilities. It assigns a numerical security score to each resource and provides actionable recommendations for hardening. Kubesec can be used as a CLI binary, Docker container, kubectl plugin, admission webhook, or REST API endpoint.

When to Use

  • When conducting security assessments that involve scanning kubernetes manifests with kubesec
  • When following incident response procedures for related security events
  • When performing scheduled security testing or auditing activities
  • When validating security controls through hands-on testing

Prerequisites

  • Kubernetes manifest files (YAML/JSON) for Deployments, Pods, DaemonSets, StatefulSets
  • Docker or Go runtime for local installation
  • kubectl access for scanning live cluster resources
  • CI/CD pipeline access for automated scanning integration

Core Concepts

Security Scoring System

Kubesec assigns a score to each Kubernetes resource based on security checks:

  • Positive scores: Awarded for security-enhancing configurations (readOnlyRootFilesystem, runAsNonRoot)
  • Zero or negative scores: Indicate missing security controls or dangerous configurations
  • Critical advisories: Flagged configurations that represent immediate security risks

Check Categories

  1. Privilege Controls: Checks for privileged containers, host PID/network access, root execution
  2. Capabilities: Identifies excessive Linux capabilities (SYS_ADMIN, NET_RAW)
  3. Volume Mounts: Detects dangerous host path mounts and writable sensitive paths
  4. Resource Limits: Validates presence of CPU/memory resource constraints
  5. Security Context: Verifies seccomp profiles, AppArmor annotations, SELinux contexts

Installation

Binary Installation

# Linux/macOS
curl -sSL https://github.com/controlplaneio/kubesec/releases/latest/download/kubesec_linux_amd64.tar.gz | \
  tar xz -C /usr/local/bin/ kubesec
 
# Verify installation
kubesec version

Docker Installation

docker pull kubesec/kubesec:v2
 
# Scan a manifest file
docker run -i kubesec/kubesec:v2 scan /dev/stdin < deployment.yaml

kubectl Plugin

kubectl krew install kubesec-scan
kubectl kubesec-scan pod mypod -n default

Practical Scanning

Scanning a Single Manifest

# Scan a deployment manifest
kubesec scan deployment.yaml
 
# Scan with JSON output
kubesec scan -o json deployment.yaml
 
# Scan from stdin
cat pod.yaml | kubesec scan -

Sample Output

[
  {
    "object": "Pod/web-app.default",
    "valid": true,
    "fileName": "pod.yaml",
    "message": "Passed with a score of 3 points",
    "score": 3,
    "scoring": {
      "passed": [
        {
          "id": "ReadOnlyRootFilesystem",
          "selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
          "reason": "An immutable root filesystem prevents applications from writing to their local disk",
          "points": 1
        },
        {
          "id": "RunAsNonRoot",
          "selector": "containers[] .securityContext .runAsNonRoot == true",
          "reason": "Force the running image to run as a non-root user",
          "points": 1
        },
        {
          "id": "LimitsCPU",
          "selector": "containers[] .resources .limits .cpu",
          "reason": "Enforcing CPU limits prevents DOS via resource exhaustion",
          "points": 1
        }
      ],
      "advise": [
        {
          "id": "ApparmorAny",
          "selector": "metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"",
          "reason": "Well defined AppArmor policies reduce the attack surface of the container",
          "points": 3
        },
        {
          "id": "ServiceAccountName",
          "selector": ".spec .serviceAccountName",
          "reason": "Service accounts restrict Kubernetes API access and should be configured",
          "points": 3
        }
      ]
    }
  }
]

Scanning Multiple Resources

# Scan all YAML files in a directory
for file in manifests/*.yaml; do
  echo "=== Scanning $file ==="
  kubesec scan "$file"
done
 
# Scan multi-document YAML
kubesec scan multi-resource.yaml

Using the HTTP API

# Scan via the public API
curl -sSX POST --data-binary @deployment.yaml \
  https://v2.kubesec.io/scan
 
# Run a local API server
kubesec http --port 8080 &
 
# Scan against local server
curl -sSX POST --data-binary @deployment.yaml \
  http://localhost:8080/scan

CI/CD Integration

GitHub Actions

name: Kubesec Scan
on: [pull_request]
jobs:
  kubesec:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Kubesec
        run: |
          curl -sSL https://github.com/controlplaneio/kubesec/releases/latest/download/kubesec_linux_amd64.tar.gz | \
            tar xz -C /usr/local/bin/ kubesec
      - name: Scan Manifests
        run: |
          FAIL=0
          for file in k8s/*.yaml; do
            SCORE=$(kubesec scan "$file" | jq '.[0].score')
            echo "$file: score=$SCORE"
            if [ "$SCORE" -lt 0 ]; then
              echo "FAIL: $file has critical issues (score: $SCORE)"
              FAIL=1
            fi
          done
          exit $FAIL

GitLab CI

kubesec-scan:
  stage: security
  image: kubesec/kubesec:v2
  script:
    - |
      for file in k8s/*.yaml; do
        kubesec scan "$file" > /tmp/result.json
        SCORE=$(cat /tmp/result.json | jq '.[0].score')
        if [ "$SCORE" -lt 0 ]; then
          echo "CRITICAL: $file scored $SCORE"
          cat /tmp/result.json | jq '.[0].scoring.critical'
          exit 1
        fi
      done
  artifacts:
    paths:
      - kubesec-results/

Admission Webhook

Deploy Kubesec as a ValidatingWebhookConfiguration to reject insecure manifests at deploy time:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: kubesec-webhook
webhooks:
  - name: kubesec.controlplane.io
    rules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        operations: ["CREATE", "UPDATE"]
        resources: ["pods"]
      - apiGroups: ["apps"]
        apiVersions: ["v1"]
        operations: ["CREATE", "UPDATE"]
        resources: ["deployments", "daemonsets", "statefulsets"]
    clientConfig:
      service:
        name: kubesec-webhook
        namespace: kube-system
        path: /scan
    failurePolicy: Fail
    sideEffects: None
    admissionReviewVersions: ["v1"]

Security Checks Reference

Critical Checks (Negative Score)

Check Selector Risk
Privileged securityContext.privileged == true Full host access
HostPID spec.hostPID == true Process namespace escape
HostNetwork spec.hostNetwork == true Network namespace escape
SYS_ADMIN capabilities.add contains SYS_ADMIN Near-root capability

Best Practice Checks (Positive Score)

Check Points Description
ReadOnlyRootFilesystem +1 Prevents filesystem writes
RunAsNonRoot +1 Non-root process execution
RunAsUser > 10000 +1 High UID reduces collision risk
LimitsCPU +1 Prevents CPU resource exhaustion
LimitsMemory +1 Prevents memory resource exhaustion
RequestsCPU +1 Ensures scheduler resource awareness
ServiceAccountName +3 Explicit service account
AppArmor annotation +3 Kernel-level MAC enforcement
Seccomp profile +4 Syscall filtering

References

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md1.8 KB

API Reference: Scanning Kubernetes Manifests with Kubesec

Kubesec CLI Commands

Command Description
kubesec scan <file> Scan a manifest file
kubesec scan -o json <file> JSON output
kubesec http --port 8080 Start local API server
kubesec version Show version info

Kubesec HTTP API

Method Endpoint Description
POST https://v2.kubesec.io/scan Public scan API
POST http://localhost:8080/scan Local scan API

Critical Checks (Negative Score)

Check Selector Risk
Privileged securityContext.privileged == true Full host access
HostPID spec.hostPID == true Process namespace escape
HostNetwork spec.hostNetwork == true Network namespace escape
SYS_ADMIN capabilities.add contains SYS_ADMIN Near-root capability

Best Practice Checks (Positive Score)

Check Points Description
ReadOnlyRootFilesystem +1 Prevents filesystem writes
RunAsNonRoot +1 Non-root execution
RunAsUser > 10000 +1 High UID
LimitsCPU +1 CPU limits set
LimitsMemory +1 Memory limits set
ServiceAccountName +3 Explicit service account
AppArmor annotation +3 MAC enforcement
Seccomp profile +4 Syscall filtering

Python Libraries

Library Version Purpose
subprocess stdlib Execute kubesec CLI
requests >=2.28 HTTP API fallback
json stdlib Parse scan results

References

standards.md1.8 KB

Standards and References - Kubesec Manifest Scanning

Industry Standards

CIS Kubernetes Benchmark v1.9

  • Section 5.2: Pod Security Standards -- Kubesec validates privileged mode, host namespaces
  • Section 5.7: General Policies -- Service account configuration, resource limits
  • Maps directly to kubesec scoring checks for container security contexts

NIST SP 800-190: Application Container Security Guide

  • Section 3.1: Image vulnerabilities and configuration defects
  • Section 3.4: Orchestrator security -- manifest validation before deployment
  • Section 4.1: Countermeasures for image vulnerabilities

Kubernetes Pod Security Standards (PSS)

  • Privileged: No restrictions (kubesec score = lowest)
  • Baseline: Prevents known privilege escalation (kubesec validates hostPID, hostNetwork, privileged)
  • Restricted: Best practices enforcement (kubesec validates all recommended controls)

Compliance Mapping

Kubesec Check CIS Control NIST 800-190 PCI DSS
Privileged containers 5.2.1 3.4.4 2.2
Host PID namespace 5.2.2 3.4.2 2.2
Host network 5.2.4 3.4.3 1.3
Root execution 5.2.6 3.4.1 7.1
ReadOnlyRootFilesystem 5.2.8 4.1.2 2.2
Resource limits 5.4.1 4.3.1 2.2
Service accounts 5.1.5 3.4.5 7.2

Tool Ecosystem

Complementary Scanning Tools

  • Kubescape: NSA/CISA framework compliance scanning
  • Checkov: Infrastructure-as-code security scanning (covers Kubernetes)
  • Datree: Policy enforcement with custom rules
  • OPA/Gatekeeper: Runtime policy enforcement as admission controller

Integration Points

  • Pre-commit hooks for developer feedback
  • CI/CD pipeline gates to prevent insecure deployments
  • Admission webhooks for runtime enforcement
  • IDE plugins for shift-left security
workflows.md2.0 KB

Workflows - Kubesec Manifest Scanning

Scanning Workflow

Pre-Commit Scanning

  1. Developer writes Kubernetes manifest locally
  2. Pre-commit hook runs kubesec scan on changed YAML files
  3. If score < 0 (critical issues), commit is blocked with remediation guidance
  4. Developer fixes issues and retries commit

CI/CD Pipeline Integration

  1. Pull request created with manifest changes
  2. CI job runs kubesec scan on all manifests in PR
  3. Results posted as PR comment with score breakdown
  4. Gate: PR blocked if any manifest scores below threshold
  5. Merge allowed only after all manifests pass minimum score

Admission Control

  1. Developer applies manifest via kubectl or GitOps
  2. ValidatingWebhook intercepts the API request
  3. Kubesec webhook scans the manifest in real-time
  4. If critical issues found, admission is denied with explanation
  5. Clean manifests are admitted to the cluster

Remediation Workflow

Scoring Improvement Process

1. Run kubesec scan on target manifest
2. Review "advise" section for point-earning improvements
3. Review "critical" section for must-fix issues
4. Apply fixes in priority order:
   a. Remove critical issues (privileged, hostPID, hostNetwork)
   b. Add seccomp profile (+4 points)
   c. Add AppArmor annotation (+3 points)
   d. Set readOnlyRootFilesystem (+1 point)
   e. Set runAsNonRoot (+1 point)
   f. Add resource limits (+1 point each)
5. Re-scan to verify improved score
6. Commit and push hardened manifest

Continuous Monitoring Workflow

Scheduled Cluster Scanning

  1. CronJob runs daily scan of all deployed resources
  2. Extracts manifests from live cluster: kubectl get deploy -o yaml
  3. Runs kubesec scan on each resource
  4. Compares scores against previous scan results
  5. Alerts on score regressions or new critical findings
  6. Generates weekly security posture report

Score Trending

Week 1: Average score 2.3  (baseline)
Week 2: Average score 3.1  (+0.8 improvement)
Week 3: Average score 4.5  (+1.4 improvement)
Week 4: Average score 5.2  (+0.7 improvement -- target: 6.0)

Scripts 2

agent.py5.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for scanning Kubernetes manifests with Kubesec.

Runs Kubesec security risk analysis on K8s manifests, evaluates
security scores, identifies critical misconfigurations, and
enforces security baselines in CI/CD pipelines.
"""

import json
import subprocess
import sys
from pathlib import Path
from datetime import datetime


class KubesecScanAgent:
    """Scans Kubernetes manifests using Kubesec for security risks."""

    def __init__(self, output_dir="./kubesec_scan"):
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        self.scan_results = []

    def scan_manifest(self, manifest_path):
        """Scan a single Kubernetes manifest file."""
        cmd = ["kubesec", "scan", manifest_path]
        try:
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
            parsed = json.loads(result.stdout) if result.stdout.strip() else []
        except FileNotFoundError:
            return self._scan_via_api(manifest_path)
        except (subprocess.TimeoutExpired, json.JSONDecodeError):
            return {"error": "Kubesec scan failed", "file": manifest_path}

        findings = []
        for item in parsed:
            findings.append({
                "object": item.get("object", ""),
                "score": item.get("score", 0),
                "message": item.get("message", ""),
                "passed": [p.get("id") for p in item.get("scoring", {}).get("passed", [])],
                "advise": [
                    {"id": a.get("id"), "reason": a.get("reason"), "points": a.get("points")}
                    for a in item.get("scoring", {}).get("advise", [])
                ],
                "critical": [
                    {"id": c.get("id"), "reason": c.get("reason")}
                    for c in item.get("scoring", {}).get("critical", [])
                ],
            })

        scan = {
            "file": manifest_path,
            "scan_date": datetime.utcnow().isoformat(),
            "findings": findings,
        }
        self.scan_results.append(scan)
        return scan

    def _scan_via_api(self, manifest_path):
        """Fallback: scan via Kubesec public HTTP API."""
        try:
            import requests
            with open(manifest_path, "rb") as f:
                resp = requests.post("https://v2.kubesec.io/scan",
                                     data=f.read(), timeout=30)
            parsed = resp.json()
            findings = []
            for item in parsed:
                findings.append({
                    "object": item.get("object", ""),
                    "score": item.get("score", 0),
                    "message": item.get("message", ""),
                    "passed": [p.get("id") for p in item.get("scoring", {}).get("passed", [])],
                    "advise": [
                        {"id": a.get("id"), "reason": a.get("reason"), "points": a.get("points")}
                        for a in item.get("scoring", {}).get("advise", [])
                    ],
                    "critical": [
                        {"id": c.get("id"), "reason": c.get("reason")}
                        for c in item.get("scoring", {}).get("critical", [])
                    ],
                })
            scan = {"file": manifest_path, "scan_date": datetime.utcnow().isoformat(), "findings": findings}
            self.scan_results.append(scan)
            return scan
        except Exception as e:
            return {"error": f"API scan failed: {e}", "file": manifest_path}

    def scan_directory(self, dir_path):
        """Scan all YAML files in a directory."""
        p = Path(dir_path)
        results = []
        for f in sorted(p.glob("*.yaml")) + sorted(p.glob("*.yml")):
            results.append(self.scan_manifest(str(f)))
        return results

    def enforce_score_threshold(self, min_score=0):
        """Check if any manifests fail the minimum score threshold."""
        failures = []
        for scan in self.scan_results:
            for finding in scan.get("findings", []):
                if finding.get("score", 0) < min_score:
                    failures.append({
                        "file": scan["file"],
                        "object": finding["object"],
                        "score": finding["score"],
                    })
                if finding.get("critical"):
                    failures.append({
                        "file": scan["file"],
                        "object": finding["object"],
                        "critical_issues": finding["critical"],
                    })
        return {"gate": "FAILED" if failures else "PASSED", "failures": failures}

    def generate_report(self):
        gate = self.enforce_score_threshold(min_score=0)
        report = {
            "report_date": datetime.utcnow().isoformat(),
            "manifests_scanned": len(self.scan_results),
            "scans": self.scan_results,
            "quality_gate": gate,
        }
        out = self.output_dir / "kubesec_report.json"
        with open(out, "w") as f:
            json.dump(report, f, indent=2)
        print(json.dumps(report, indent=2))
        return report


def main():
    if len(sys.argv) < 2:
        print("Usage: agent.py <manifest.yaml|directory> [--min-score 0]")
        sys.exit(1)

    target = sys.argv[1]
    min_score = 0
    if "--min-score" in sys.argv:
        min_score = int(sys.argv[sys.argv.index("--min-score") + 1])

    agent = KubesecScanAgent()
    if Path(target).is_dir():
        agent.scan_directory(target)
    else:
        agent.scan_manifest(target)

    report = agent.generate_report()
    gate = agent.enforce_score_threshold(min_score)
    if gate["gate"] == "FAILED":
        sys.exit(1)


if __name__ == "__main__":
    main()
process.py8.3 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Kubesec Manifest Scanner Automation

Scans Kubernetes manifests using Kubesec, aggregates results,
and generates security posture reports with remediation guidance.
"""

import json
import subprocess
import sys
import argparse
from pathlib import Path
from collections import defaultdict


MINIMUM_SCORE_THRESHOLD = 0
RECOMMENDED_SCORE_THRESHOLD = 5


def scan_manifest_with_kubesec(file_path: str, kubesec_url: str = "") -> list[dict]:
    """Scan a single manifest file using kubesec."""
    path = Path(file_path)
    if not path.exists():
        print(f"[ERROR] File not found: {file_path}")
        return []

    try:
        if kubesec_url:
            result = subprocess.run(
                ["curl", "-sSX", "POST", "--data-binary", f"@{file_path}", f"{kubesec_url}/scan"],
                capture_output=True, text=True, timeout=30
            )
        else:
            result = subprocess.run(
                ["kubesec", "scan", file_path],
                capture_output=True, text=True, timeout=30
            )

        if result.returncode != 0:
            print(f"[ERROR] Scan failed for {file_path}: {result.stderr.strip()}")
            return []

        return json.loads(result.stdout)
    except FileNotFoundError:
        print("[ERROR] kubesec binary not found. Install from https://github.com/controlplaneio/kubesec")
        return []
    except json.JSONDecodeError:
        print(f"[ERROR] Invalid JSON output from kubesec for {file_path}")
        return []
    except subprocess.TimeoutExpired:
        print(f"[ERROR] Timeout scanning {file_path}")
        return []


def scan_directory(directory: str, kubesec_url: str = "") -> list[dict]:
    """Scan all YAML/JSON files in a directory."""
    dir_path = Path(directory)
    if not dir_path.is_dir():
        print(f"[ERROR] Directory not found: {directory}")
        return []

    all_results = []
    yaml_files = list(dir_path.glob("**/*.yaml")) + list(dir_path.glob("**/*.yml")) + list(dir_path.glob("**/*.json"))

    for manifest_file in sorted(yaml_files):
        print(f"[INFO] Scanning {manifest_file}...")
        results = scan_manifest_with_kubesec(str(manifest_file), kubesec_url)
        for r in results:
            r["source_file"] = str(manifest_file)
        all_results.extend(results)

    return all_results


def categorize_findings(results: list[dict]) -> dict:
    """Categorize scan findings by severity."""
    categories = {
        "critical": [],
        "warning": [],
        "info": [],
        "passed": []
    }

    for result in results:
        score = result.get("score", 0)
        obj = result.get("object", "unknown")
        source = result.get("source_file", "unknown")
        scoring = result.get("scoring", {})

        entry = {
            "object": obj,
            "source_file": source,
            "score": score,
            "critical": scoring.get("critical", []),
            "advise": scoring.get("advise", []),
            "passed": scoring.get("passed", [])
        }

        if score < 0:
            categories["critical"].append(entry)
        elif score < RECOMMENDED_SCORE_THRESHOLD:
            categories["warning"].append(entry)
        else:
            categories["passed"].append(entry)

    return categories


def generate_remediation(result: dict) -> list[str]:
    """Generate remediation recommendations for a scan result."""
    remediations = []
    scoring = result.get("scoring", {})

    for critical in scoring.get("critical", []):
        check_id = critical.get("id", "")
        selector = critical.get("selector", "")
        reason = critical.get("reason", "")
        remediations.append(f"[CRITICAL] {check_id}: {reason} (fix: {selector})")

    for advise in scoring.get("advise", []):
        check_id = advise.get("id", "")
        reason = advise.get("reason", "")
        points = advise.get("points", 0)
        remediations.append(f"[ADVISE +{points}pts] {check_id}: {reason}")

    return remediations


def generate_report(results: list[dict], output_format: str = "text") -> str:
    """Generate a comprehensive scanning report."""
    categories = categorize_findings(results)

    if output_format == "json":
        report = {
            "total_resources_scanned": len(results),
            "critical_count": len(categories["critical"]),
            "warning_count": len(categories["warning"]),
            "passed_count": len(categories["passed"]),
            "results": results,
            "categories": categories
        }
        return json.dumps(report, indent=2)

    lines = []
    lines.append("=" * 70)
    lines.append("KUBESEC MANIFEST SECURITY SCAN REPORT")
    lines.append("=" * 70)

    lines.append(f"\nTotal Resources Scanned: {len(results)}")
    lines.append(f"  Critical (score < 0): {len(categories['critical'])}")
    lines.append(f"  Warning (score < {RECOMMENDED_SCORE_THRESHOLD}): {len(categories['warning'])}")
    lines.append(f"  Passed (score >= {RECOMMENDED_SCORE_THRESHOLD}): {len(categories['passed'])}")

    if results:
        scores = [r.get("score", 0) for r in results]
        lines.append(f"\nScore Statistics:")
        lines.append(f"  Average: {sum(scores) / len(scores):.1f}")
        lines.append(f"  Min: {min(scores)}")
        lines.append(f"  Max: {max(scores)}")

    if categories["critical"]:
        lines.append(f"\n{'=' * 50}")
        lines.append("CRITICAL FINDINGS")
        lines.append(f"{'=' * 50}")
        for item in categories["critical"]:
            lines.append(f"\n  Resource: {item['object']}")
            lines.append(f"  File: {item['source_file']}")
            lines.append(f"  Score: {item['score']}")
            for crit in item["critical"]:
                lines.append(f"    [CRITICAL] {crit.get('id', '')}: {crit.get('reason', '')}")

    if categories["warning"]:
        lines.append(f"\n{'=' * 50}")
        lines.append("WARNINGS")
        lines.append(f"{'=' * 50}")
        for item in categories["warning"]:
            lines.append(f"\n  Resource: {item['object']}")
            lines.append(f"  File: {item['source_file']}")
            lines.append(f"  Score: {item['score']}")
            for adv in item["advise"][:5]:
                lines.append(f"    [ADVISE +{adv.get('points', 0)}] {adv.get('id', '')}: {adv.get('reason', '')}")

    lines.append(f"\n{'=' * 50}")
    lines.append("REMEDIATION SUMMARY")
    lines.append(f"{'=' * 50}")

    advise_counts = defaultdict(int)
    for result in results:
        for adv in result.get("scoring", {}).get("advise", []):
            advise_counts[adv.get("id", "")] += 1

    lines.append("\nMost Common Missing Controls:")
    for check, count in sorted(advise_counts.items(), key=lambda x: -x[1])[:10]:
        lines.append(f"  {check}: missing in {count}/{len(results)} resources")

    gate_pass = all(r.get("score", 0) >= MINIMUM_SCORE_THRESHOLD for r in results)
    lines.append(f"\n{'=' * 50}")
    lines.append(f"GATE RESULT: {'PASS' if gate_pass else 'FAIL'}")
    lines.append(f"{'=' * 50}")

    return "\n".join(lines)


def main():
    parser = argparse.ArgumentParser(description="Kubesec Manifest Scanner Automation")
    parser.add_argument("--file", help="Single manifest file to scan")
    parser.add_argument("--directory", help="Directory containing manifests to scan")
    parser.add_argument("--url", default="", help="Kubesec API URL (optional, uses local binary if not set)")
    parser.add_argument("--format", choices=["text", "json"], default="text", help="Output format")
    parser.add_argument("--threshold", type=int, default=0, help="Minimum passing score (default: 0)")
    args = parser.parse_args()

    global MINIMUM_SCORE_THRESHOLD
    MINIMUM_SCORE_THRESHOLD = args.threshold

    if not args.file and not args.directory:
        print("[ERROR] Specify --file or --directory")
        sys.exit(1)

    results = []
    if args.file:
        results = scan_manifest_with_kubesec(args.file, args.url)
        for r in results:
            r["source_file"] = args.file
    elif args.directory:
        results = scan_directory(args.directory, args.url)

    if not results:
        print("[WARN] No scan results generated")
        sys.exit(1)

    report = generate_report(results, args.format)
    print(report)

    has_critical = any(r.get("score", 0) < MINIMUM_SCORE_THRESHOLD for r in results)
    sys.exit(1 if has_critical else 0)


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 1.1 KB
Keep exploring