mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-18 21:49:40 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
---
|
||||
name: building-devsecops-pipeline-with-gitlab-ci
|
||||
description: Design and implement a comprehensive DevSecOps pipeline in GitLab CI/CD integrating SAST, DAST, container scanning, dependency scanning, and secret detection.
|
||||
domain: cybersecurity
|
||||
subdomain: devsecops
|
||||
tags: [gitlab-ci, devsecops, sast, dast, container-scanning, dependency-scanning, secret-detection, cicd-security]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Building DevSecOps Pipeline with GitLab CI
|
||||
|
||||
## Overview
|
||||
|
||||
GitLab provides an integrated DevSecOps platform that embeds security testing directly into the CI/CD pipeline. By leveraging GitLab's built-in security scanners---SAST, DAST, container scanning, dependency scanning, secret detection, and license compliance---teams can shift security left, catching vulnerabilities during development rather than post-deployment. GitLab Duo AI assists with false positive detection for SAST vulnerabilities, helping security teams focus on genuine issues.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- GitLab Ultimate license (required for full security scanner suite)
|
||||
- GitLab Runner configured (shared or self-hosted)
|
||||
- `.gitlab-ci.yml` pipeline configuration familiarity
|
||||
- Docker-in-Docker (DinD) or Kaniko for container builds
|
||||
- Application deployed to a staging environment for DAST scanning
|
||||
|
||||
## Core Security Scanning Stages
|
||||
|
||||
### Static Application Security Testing (SAST)
|
||||
|
||||
SAST analyzes source code for vulnerabilities before compilation. GitLab supports 14+ languages using analyzers such as Semgrep, SpotBugs, Gosec, Bandit, and NodeJsScan. The simplest inclusion uses GitLab's managed templates.
|
||||
|
||||
### Dynamic Application Security Testing (DAST)
|
||||
|
||||
DAST tests running applications by simulating attack payloads against HTTP endpoints. It detects XSS, SQLi, CSRF, and other runtime vulnerabilities that static analysis cannot find. DAST requires a deployed, accessible target URL.
|
||||
|
||||
### Container Scanning
|
||||
|
||||
Uses Trivy to scan Docker images for known CVEs in OS packages and application dependencies. Runs after the Docker build stage to gate images before they reach a registry.
|
||||
|
||||
### Dependency Scanning
|
||||
|
||||
Inspects dependency manifests (package.json, requirements.txt, pom.xml, Gemfile.lock) for known vulnerable versions. Operates at the source code level, complementing container scanning.
|
||||
|
||||
### Secret Detection
|
||||
|
||||
Scans commits for accidentally committed credentials, API keys, tokens, and private keys using pattern matching and entropy analysis. Runs on every commit to prevent secrets from reaching the repository.
|
||||
|
||||
## Implementation
|
||||
|
||||
### Complete Pipeline Configuration
|
||||
|
||||
```yaml
|
||||
# .gitlab-ci.yml
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- security
|
||||
- deploy-staging
|
||||
- dast
|
||||
- deploy-production
|
||||
|
||||
variables:
|
||||
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
|
||||
SECURE_LOG_LEVEL: "info"
|
||||
|
||||
# Include GitLab managed security templates
|
||||
include:
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
- template: Security/Secret-Detection.gitlab-ci.yml
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
- template: Security/Container-Scanning.gitlab-ci.yml
|
||||
- template: DAST.gitlab-ci.yml
|
||||
- template: Security/License-Scanning.gitlab-ci.yml
|
||||
|
||||
build:
|
||||
stage: build
|
||||
image: docker:24.0
|
||||
services:
|
||||
- docker:24.0-dind
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
- docker build -t $DOCKER_IMAGE .
|
||||
- docker push $DOCKER_IMAGE
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
|
||||
unit-tests:
|
||||
stage: test
|
||||
image: $DOCKER_IMAGE
|
||||
script:
|
||||
- npm ci
|
||||
- npm run test:coverage
|
||||
coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
|
||||
artifacts:
|
||||
reports:
|
||||
junit: junit-report.xml
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage/cobertura-coverage.xml
|
||||
|
||||
# Override SAST to run in security stage
|
||||
sast:
|
||||
stage: security
|
||||
variables:
|
||||
SAST_EXCLUDED_PATHS: "spec,test,tests,tmp,node_modules"
|
||||
SEARCH_MAX_DEPTH: 10
|
||||
|
||||
# Override container scanning
|
||||
container_scanning:
|
||||
stage: security
|
||||
variables:
|
||||
CS_IMAGE: $DOCKER_IMAGE
|
||||
CS_SEVERITY_THRESHOLD: "HIGH"
|
||||
|
||||
# Override dependency scanning
|
||||
dependency_scanning:
|
||||
stage: security
|
||||
|
||||
# Override secret detection
|
||||
secret_detection:
|
||||
stage: security
|
||||
|
||||
# License compliance scanning
|
||||
license_scanning:
|
||||
stage: security
|
||||
|
||||
deploy-staging:
|
||||
stage: deploy-staging
|
||||
image: bitnami/kubectl:latest
|
||||
script:
|
||||
- kubectl set image deployment/app app=$DOCKER_IMAGE -n staging
|
||||
- kubectl rollout status deployment/app -n staging --timeout=300s
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.example.com
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
|
||||
# DAST runs against deployed staging
|
||||
dast:
|
||||
stage: dast
|
||||
variables:
|
||||
DAST_WEBSITE: https://staging.example.com
|
||||
DAST_FULL_SCAN_ENABLED: "true"
|
||||
DAST_BROWSER_SCAN: "true"
|
||||
needs:
|
||||
- deploy-staging
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
|
||||
deploy-production:
|
||||
stage: deploy-production
|
||||
image: bitnami/kubectl:latest
|
||||
script:
|
||||
- kubectl set image deployment/app app=$DOCKER_IMAGE -n production
|
||||
- kubectl rollout status deployment/app -n production --timeout=300s
|
||||
environment:
|
||||
name: production
|
||||
url: https://app.example.com
|
||||
when: manual
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
```
|
||||
|
||||
### Security Approval Policies
|
||||
|
||||
Configure scan execution policies to enforce mandatory security scans:
|
||||
|
||||
1. Navigate to Security & Compliance > Policies
|
||||
2. Create a "Scan Execution Policy" requiring SAST and secret detection on all branches
|
||||
3. Create a "Merge Request Approval Policy" requiring security team approval when critical vulnerabilities are detected
|
||||
|
||||
### Custom SAST Ruleset Configuration
|
||||
|
||||
Create `.gitlab/sast-ruleset.toml` to customize analyzer behavior:
|
||||
|
||||
```toml
|
||||
[semgrep]
|
||||
[[semgrep.ruleset]]
|
||||
dirs = ["src"]
|
||||
|
||||
[[semgrep.passthrough]]
|
||||
type = "url"
|
||||
target = "/sgrep-rules/custom-rules.yml"
|
||||
value = "https://semgrep.dev/p/owasp-top-ten"
|
||||
|
||||
[[semgrep.passthrough]]
|
||||
type = "url"
|
||||
target = "/sgrep-rules/java-rules.yml"
|
||||
value = "https://semgrep.dev/p/java"
|
||||
```
|
||||
|
||||
## Security Dashboard and Vulnerability Management
|
||||
|
||||
### Vulnerability Report
|
||||
|
||||
GitLab consolidates all scanner findings into a single Vulnerability Report accessible at Security & Compliance > Vulnerability Report. Each vulnerability includes:
|
||||
- Severity rating (Critical, High, Medium, Low, Info)
|
||||
- Scanner source (SAST, DAST, Container, Dependency, Secret)
|
||||
- Location in source code or image layer
|
||||
- Remediation guidance and suggested fixes
|
||||
- Status tracking (Detected, Confirmed, Dismissed, Resolved)
|
||||
|
||||
### Merge Request Security Widget
|
||||
|
||||
Every merge request displays a security scanning widget showing:
|
||||
- New vulnerabilities introduced by the MR
|
||||
- Fixed vulnerabilities resolved by the MR
|
||||
- Comparison against the target branch baseline
|
||||
|
||||
## Pipeline Optimization
|
||||
|
||||
- **Parallel execution**: Security scanners run concurrently in the security stage
|
||||
- **Caching**: Use CI cache for dependency downloads to speed up scanning
|
||||
- **Incremental scanning**: SAST can scan only changed files using `SAST_INCREMENTAL: "true"`
|
||||
- **Fail conditions**: Set `allow_failure: false` on critical scanners to enforce quality gates
|
||||
|
||||
## Monitoring and Metrics
|
||||
|
||||
| Metric | Description | Target |
|
||||
|--------|-------------|--------|
|
||||
| Pipeline security coverage | Percentage of projects with all scanners enabled | > 95% |
|
||||
| Critical vulnerability MTTR | Time from detection to resolution for critical findings | < 48 hours |
|
||||
| False positive rate | Percentage of dismissed-as-false-positive findings | < 15% |
|
||||
| Secret detection block rate | Percentage of secret commits blocked by push rules | > 99% |
|
||||
|
||||
## References
|
||||
|
||||
- [GitLab Security Scanning Documentation](https://docs.gitlab.com/ee/user/application_security/)
|
||||
- [GitLab SAST Analyzers](https://docs.gitlab.com/ee/user/application_security/sast/)
|
||||
- [GitLab DAST Configuration](https://docs.gitlab.com/ee/user/application_security/dast/)
|
||||
- [GitLab Security Policies](https://docs.gitlab.com/ee/user/application_security/policies/)
|
||||
- [GitLab Vulnerability Management](https://docs.gitlab.com/ee/user/application_security/vulnerability_report/)
|
||||
@@ -0,0 +1,35 @@
|
||||
# GitLab DevSecOps Pipeline Implementation Template
|
||||
|
||||
## Pipeline Security Scanner Checklist
|
||||
|
||||
| Scanner | Enabled | Template Included | Threshold Set | Blocking |
|
||||
|---------|---------|-------------------|---------------|----------|
|
||||
| SAST | [ ] | [ ] | Severity: _____ | [ ] |
|
||||
| DAST | [ ] | [ ] | Severity: _____ | [ ] |
|
||||
| Container Scanning | [ ] | [ ] | Severity: _____ | [ ] |
|
||||
| Dependency Scanning | [ ] | [ ] | Severity: _____ | [ ] |
|
||||
| Secret Detection | [ ] | [ ] | N/A | [ ] |
|
||||
| License Scanning | [ ] | [ ] | Policy: _____ | [ ] |
|
||||
|
||||
## Security Policy Configuration
|
||||
|
||||
| Policy Type | Name | Scope | Enforcement |
|
||||
|-------------|------|-------|-------------|
|
||||
| Scan Execution | | [ ] All branches [ ] Default only | [ ] Required |
|
||||
| MR Approval | | Severity trigger: _____ | Approvers: _____ |
|
||||
|
||||
## Environment-Specific DAST Targets
|
||||
|
||||
| Environment | URL | Auth Method | Scan Type | Schedule |
|
||||
|-------------|-----|-------------|-----------|----------|
|
||||
| Staging | | [ ] None [ ] Token [ ] Cookie | [ ] Passive [ ] Full | |
|
||||
| Pre-production | | [ ] None [ ] Token [ ] Cookie | [ ] Passive [ ] Full | |
|
||||
|
||||
## Vulnerability SLA Targets
|
||||
|
||||
| Severity | Detection to Triage | Triage to Fix | Total SLA |
|
||||
|----------|--------------------|--------------|-----------|
|
||||
| Critical | 4 hours | 24 hours | 48 hours |
|
||||
| High | 24 hours | 5 days | 7 days |
|
||||
| Medium | 48 hours | 14 days | 30 days |
|
||||
| Low | 1 week | 30 days | 90 days |
|
||||
@@ -0,0 +1,48 @@
|
||||
# Standards and Compliance Reference
|
||||
|
||||
## OWASP DevSecOps Pipeline Maturity Model
|
||||
|
||||
| Level | SAST | DAST | SCA | Container | Secrets | License |
|
||||
|-------|------|------|-----|-----------|---------|---------|
|
||||
| Level 1 (Basic) | Manual runs | None | Manual dependency check | None | Pre-commit hooks | None |
|
||||
| Level 2 (Integrated) | CI-triggered on MR | Scheduled scans | CI-triggered | Image scan on build | CI scan on commits | CI-triggered |
|
||||
| Level 3 (Enforced) | Required for merge | Gate before deploy | Block on critical CVE | Block vulnerable images | Push protection | Policy enforcement |
|
||||
| Level 4 (Optimized) | Custom rules, tuned FP | Authenticated full scan | Auto-remediation PRs | Signed images only | Auto-rotation | SBOM generation |
|
||||
|
||||
## NIST SP 800-218 (SSDF) Mapping
|
||||
|
||||
| SSDF Practice | GitLab Feature | Pipeline Stage |
|
||||
|---------------|----------------|----------------|
|
||||
| PO.1 Define security requirements | Security policies | Policy configuration |
|
||||
| PW.1 Design software securely | Threat modeling integration | Pre-build |
|
||||
| PW.4 Reuse well-secured software | Dependency scanning | Security stage |
|
||||
| PW.5 Create source code securely | SAST, secret detection | Security stage |
|
||||
| PW.7 Review and test code | MR security widget | Merge request |
|
||||
| PW.8 Test executable code | DAST | Post-deploy staging |
|
||||
| PW.9 Configure software securely | Container scanning | Security stage |
|
||||
| RV.1 Identify vulnerabilities | Vulnerability report | Dashboard |
|
||||
| RV.2 Assess and prioritize | Severity classification | Triage workflow |
|
||||
| RV.3 Remediate vulnerabilities | Issue tracking integration | Sprint planning |
|
||||
|
||||
## CIS Software Supply Chain Security
|
||||
|
||||
- **SCS-1**: Secure source code management with protected branches and signed commits
|
||||
- **SCS-2**: Secure build pipelines with pinned template versions and runner isolation
|
||||
- **SCS-3**: Verified dependencies through dependency scanning and license compliance
|
||||
- **SCS-4**: Secure artifacts with container scanning and signed images
|
||||
- **SCS-5**: Deployment security with manual gates and environment approvals
|
||||
|
||||
## GitLab Scanner Coverage Matrix
|
||||
|
||||
| Vulnerability Type | Primary Scanner | Secondary Scanner |
|
||||
|--------------------|-----------------|-------------------|
|
||||
| SQL Injection | SAST (Semgrep) | DAST |
|
||||
| XSS | SAST | DAST |
|
||||
| SSRF | SAST | DAST |
|
||||
| Command Injection | SAST | DAST |
|
||||
| Insecure Deserialization | SAST | N/A |
|
||||
| Known CVE in dependency | Dependency Scanning | Container Scanning |
|
||||
| Hardcoded credentials | Secret Detection | SAST |
|
||||
| License violation | License Scanning | N/A |
|
||||
| OS-level CVE in image | Container Scanning | N/A |
|
||||
| Authentication flaws | DAST | SAST |
|
||||
@@ -0,0 +1,84 @@
|
||||
# GitLab DevSecOps Pipeline Workflows
|
||||
|
||||
## Workflow 1: Merge Request Security Review
|
||||
|
||||
```
|
||||
Developer creates merge request
|
||||
|
|
||||
Pipeline triggers security scanners in parallel:
|
||||
[SAST] [Secret Detection] [Dependency Scanning] [License Scanning]
|
||||
|
|
||||
MR Security Widget displays results:
|
||||
- New vulnerabilities introduced
|
||||
- Existing vulnerabilities fixed
|
||||
- Comparison with target branch
|
||||
|
|
||||
[No Critical/High] --> Reviewers can approve and merge
|
||||
[Critical/High found] --> MR blocked by approval policy
|
||||
|
|
||||
Security team reviews findings
|
||||
|
|
||||
[Confirmed] --> Developer remediates and re-pushes
|
||||
[False Positive] --> Dismissed with documented reason
|
||||
|
|
||||
All findings resolved --> MR eligible for merge
|
||||
```
|
||||
|
||||
## Workflow 2: Container Image Security Gate
|
||||
|
||||
```
|
||||
Docker image built in CI
|
||||
|
|
||||
Container scanning (Trivy) analyzes image layers
|
||||
|
|
||||
Findings categorized by severity
|
||||
|
|
||||
[Below threshold] --> Image pushed to registry with metadata
|
||||
[Above threshold] --> Pipeline fails, image not pushed
|
||||
|
|
||||
Registry stores scan results as artifact
|
||||
|
|
||||
Deployment pulls only scanned/approved images
|
||||
```
|
||||
|
||||
## Workflow 3: DAST Against Staging Environment
|
||||
|
||||
```
|
||||
Application deployed to staging
|
||||
|
|
||||
DAST browser scan initiated against staging URL
|
||||
|
|
||||
Authenticated scan crawls application pages
|
||||
|
|
||||
Active testing for XSS, SQLi, CSRF, etc.
|
||||
|
|
||||
Results added to vulnerability report
|
||||
|
|
||||
[Pass] --> Manual deploy-to-production gate enabled
|
||||
[Fail on critical] --> Staging deployment rolled back
|
||||
|
|
||||
Production deploy requires manual approval
|
||||
```
|
||||
|
||||
## Workflow 4: Vulnerability Lifecycle Management
|
||||
|
||||
```
|
||||
Scanner detects vulnerability
|
||||
|
|
||||
Status: "Detected" in vulnerability report
|
||||
|
|
||||
Security analyst triages finding
|
||||
|
|
||||
[Confirmed vulnerability] [False positive]
|
||||
| |
|
||||
Status: "Confirmed" Status: "Dismissed"
|
||||
Issue created automatically Reason documented
|
||||
|
|
||||
Developer assigned fix
|
||||
|
|
||||
Fix merged, scanner re-runs
|
||||
|
|
||||
Vulnerability no longer detected
|
||||
|
|
||||
Status: "Resolved"
|
||||
```
|
||||
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
GitLab DevSecOps Pipeline Security Report Generator
|
||||
|
||||
Queries GitLab API to aggregate security scanning results
|
||||
across projects and generate compliance reports.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def gitlab_api_get(url: str, token: str) -> list | dict:
|
||||
headers = {"PRIVATE-TOKEN": token, "Content-Type": "application/json"}
|
||||
results = []
|
||||
page = 1
|
||||
while True:
|
||||
sep = "&" if "?" in url else "?"
|
||||
paginated = f"{url}{sep}per_page=100&page={page}"
|
||||
req = urllib.request.Request(paginated, headers=headers)
|
||||
try:
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
data = json.loads(resp.read().decode())
|
||||
if isinstance(data, list):
|
||||
if not data:
|
||||
break
|
||||
results.extend(data)
|
||||
page += 1
|
||||
else:
|
||||
return data
|
||||
except urllib.error.HTTPError as e:
|
||||
print(f"HTTP {e.code}: {e.read().decode()}")
|
||||
break
|
||||
return results
|
||||
|
||||
|
||||
def get_group_projects(base_url: str, token: str, group_id: str) -> list:
|
||||
url = f"{base_url}/api/v4/groups/{group_id}/projects?include_subgroups=true"
|
||||
return gitlab_api_get(url, token)
|
||||
|
||||
|
||||
def get_project_vulnerabilities(base_url: str, token: str, project_id: int) -> list:
|
||||
url = f"{base_url}/api/v4/projects/{project_id}/vulnerabilities?state=detected"
|
||||
return gitlab_api_get(url, token)
|
||||
|
||||
|
||||
def get_pipeline_jobs(base_url: str, token: str, project_id: int, pipeline_id: int) -> list:
|
||||
url = f"{base_url}/api/v4/projects/{project_id}/pipelines/{pipeline_id}/jobs"
|
||||
return gitlab_api_get(url, token)
|
||||
|
||||
|
||||
def check_security_scanners(jobs: list) -> dict:
|
||||
scanner_names = {
|
||||
"sast": False,
|
||||
"secret_detection": False,
|
||||
"dependency_scanning": False,
|
||||
"container_scanning": False,
|
||||
"dast": False,
|
||||
"license_scanning": False,
|
||||
}
|
||||
for job in jobs:
|
||||
name = job.get("name", "").lower()
|
||||
for scanner in scanner_names:
|
||||
if scanner.replace("_", "-") in name or scanner in name:
|
||||
scanner_names[scanner] = True
|
||||
return scanner_names
|
||||
|
||||
|
||||
def generate_report(base_url: str, token: str, group_id: str) -> dict:
|
||||
projects = get_group_projects(base_url, token, group_id)
|
||||
report = {
|
||||
"gitlab_instance": base_url,
|
||||
"group_id": group_id,
|
||||
"generated_at": datetime.utcnow().isoformat() + "Z",
|
||||
"total_projects": len(projects),
|
||||
"scanner_coverage": defaultdict(int),
|
||||
"severity_totals": defaultdict(int),
|
||||
"project_details": [],
|
||||
}
|
||||
|
||||
for project in projects:
|
||||
pid = project["id"]
|
||||
name = project["path_with_namespace"]
|
||||
|
||||
vulns = get_project_vulnerabilities(base_url, token, pid)
|
||||
severity_counts = defaultdict(int)
|
||||
scanner_counts = defaultdict(int)
|
||||
for v in vulns:
|
||||
severity_counts[v.get("severity", "unknown")] += 1
|
||||
scanner_counts[v.get("scanner", {}).get("name", "unknown")] += 1
|
||||
report["severity_totals"][v.get("severity", "unknown")] += 1
|
||||
|
||||
pipelines = gitlab_api_get(
|
||||
f"{base_url}/api/v4/projects/{pid}/pipelines?per_page=1&status=success", token
|
||||
)
|
||||
scanners_enabled = {}
|
||||
if pipelines and isinstance(pipelines, list):
|
||||
jobs = get_pipeline_jobs(base_url, token, pid, pipelines[0]["id"])
|
||||
scanners_enabled = check_security_scanners(jobs)
|
||||
for scanner, enabled in scanners_enabled.items():
|
||||
if enabled:
|
||||
report["scanner_coverage"][scanner] += 1
|
||||
|
||||
report["project_details"].append({
|
||||
"project": name,
|
||||
"open_vulnerabilities": len(vulns),
|
||||
"by_severity": dict(severity_counts),
|
||||
"by_scanner": dict(scanner_counts),
|
||||
"scanners_enabled": scanners_enabled,
|
||||
})
|
||||
|
||||
report["scanner_coverage"] = dict(report["scanner_coverage"])
|
||||
report["severity_totals"] = dict(report["severity_totals"])
|
||||
return report
|
||||
|
||||
|
||||
def print_report(report: dict) -> None:
|
||||
print(f"\n{'='*65}")
|
||||
print(f"GitLab DevSecOps Security Report")
|
||||
print(f"Instance: {report['gitlab_instance']}")
|
||||
print(f"Generated: {report['generated_at']}")
|
||||
print(f"{'='*65}")
|
||||
print(f"\nTotal Projects: {report['total_projects']}")
|
||||
|
||||
print(f"\nScanner Coverage:")
|
||||
for scanner, count in sorted(report["scanner_coverage"].items()):
|
||||
pct = count / report["total_projects"] * 100 if report["total_projects"] > 0 else 0
|
||||
print(f" {scanner:25s}: {count:3d}/{report['total_projects']} ({pct:.0f}%)")
|
||||
|
||||
print(f"\nVulnerability Summary:")
|
||||
for sev in ["critical", "high", "medium", "low", "info", "unknown"]:
|
||||
count = report["severity_totals"].get(sev, 0)
|
||||
if count > 0:
|
||||
print(f" {sev.upper():12s}: {count}")
|
||||
|
||||
total = sum(report["severity_totals"].values())
|
||||
print(f" {'TOTAL':12s}: {total}")
|
||||
|
||||
print(f"\nTop 10 Projects by Open Vulnerabilities:")
|
||||
sorted_projects = sorted(
|
||||
report["project_details"], key=lambda p: p["open_vulnerabilities"], reverse=True
|
||||
)
|
||||
for p in sorted_projects[:10]:
|
||||
print(f" {p['project']:45s} | Vulns: {p['open_vulnerabilities']}")
|
||||
|
||||
|
||||
def main():
|
||||
token = os.environ.get("GITLAB_TOKEN")
|
||||
base_url = os.environ.get("GITLAB_URL", "https://gitlab.com")
|
||||
group_id = os.environ.get("GITLAB_GROUP_ID")
|
||||
|
||||
if not token:
|
||||
print("Error: GITLAB_TOKEN environment variable required")
|
||||
sys.exit(1)
|
||||
if not group_id:
|
||||
print("Error: GITLAB_GROUP_ID environment variable required")
|
||||
sys.exit(1)
|
||||
|
||||
report = generate_report(base_url, token, group_id)
|
||||
print_report(report)
|
||||
|
||||
output = f"gitlab_devsecops_report_{datetime.utcnow().strftime('%Y%m%d')}.json"
|
||||
with open(output, "w") as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
print(f"\nReport saved to: {output}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user