diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..3687428
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,103 @@
+version: 2
+updates:
+ # Python dependencies
+ - package-ecosystem: "pip"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ time: "09:00"
+ open-pull-requests-limit: 10
+ assignees:
+ - "jmessiass"
+ commit-message:
+ prefix: "chore"
+ include: "scope"
+ labels:
+ - "dependencies"
+ - "security"
+
+ # Python app dependencies
+ - package-ecosystem: "pip"
+ directory: "/app"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ time: "09:00"
+ open-pull-requests-limit: 5
+ assignees:
+ - "jmessiass"
+ commit-message:
+ prefix: "chore"
+ include: "scope"
+ labels:
+ - "dependencies"
+ - "app"
+
+ # Tasks dependencies
+ - package-ecosystem: "pip"
+ directory: "/tasks"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ time: "09:00"
+ open-pull-requests-limit: 5
+ assignees:
+ - "jmessiass"
+ commit-message:
+ prefix: "chore"
+ include: "scope"
+ labels:
+ - "dependencies"
+ - "tasks"
+
+ # Tests dependencies
+ - package-ecosystem: "pip"
+ directory: "/tests"
+ schedule:
+ interval: "weekly"
+ day: "monday"
+ time: "09:00"
+ open-pull-requests-limit: 5
+ assignees:
+ - "jmessiass"
+ commit-message:
+ prefix: "chore"
+ include: "scope"
+ labels:
+ - "dependencies"
+ - "tests"
+
+ # Docker dependencies
+ - package-ecosystem: "docker"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "tuesday"
+ time: "09:00"
+ open-pull-requests-limit: 5
+ assignees:
+ - "jmessiass"
+ commit-message:
+ prefix: "chore"
+ include: "scope"
+ labels:
+ - "dependencies"
+ - "docker"
+
+ # GitHub Actions dependencies
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "wednesday"
+ time: "09:00"
+ open-pull-requests-limit: 5
+ assignees:
+ - "jmessiass"
+ commit-message:
+ prefix: "chore"
+ include: "scope"
+ labels:
+ - "dependencies"
+ - "github-actions"
\ No newline at end of file
diff --git a/.github/workflows/codeql.yml.disabled b/.github/workflows/codeql.yml.disabled
new file mode 100644
index 0000000..df0c105
--- /dev/null
+++ b/.github/workflows/codeql.yml.disabled
@@ -0,0 +1,41 @@
+name: "CodeQL Analysis"
+
+on:
+ push:
+ branches: [ "main", "dev" ]
+ pull_request:
+ branches: [ "main" ]
+ schedule:
+ - cron: '30 3 * * 1'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ timeout-minutes: 360
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'python' ]
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v3
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
\ No newline at end of file
diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml
index 51fdd5e..1c07431 100644
--- a/.github/workflows/security.yml
+++ b/.github/workflows/security.yml
@@ -7,24 +7,16 @@ on:
branches: [main]
env:
- # Configurações globais
- FAIL_ON_SEVERITY: "CRITICAL,HIGH"
SARIF_RESULTS_DIR: "security-results"
jobs:
- # Job de preparação - cria diretório para resultados
- setup:
+ # SAST - Complementa o Code Scanning nativo
+ sast-semgrep:
runs-on: ubuntu-latest
- outputs:
- sarif-dir: ${{ env.SARIF_RESULTS_DIR }}
- steps:
- - name: Create results directory
- run: mkdir -p ${{ env.SARIF_RESULTS_DIR }}
-
- # SAST - Static Application Security Testing
- sast:
- runs-on: ubuntu-latest
- needs: setup
+ permissions:
+ security-events: write
+ contents: read
+ actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -38,79 +30,38 @@ jobs:
p/security-audit
p/secrets
p/owasp-top-ten
- generateSarif: "1"
-
- - name: Upload SAST results
- uses: actions/upload-artifact@v4
- if: always()
- with:
- name: sast-results
- path: semgrep.sarif
- retention-days: 30
-
- - name: Upload to GitHub Security tab
+ p/python
+ p/flask
+ p/django
+ p/sql-injection
+ p/command-injection
+ continue-on-error: true
+
+ - name: Check if Semgrep SARIF file exists
+ id: check-semgrep-sarif
+ run: |
+ echo "Files in current directory:"
+ ls -la *.sarif 2>/dev/null || echo "No SARIF files found"
+ if [ -f "semgrep.sarif" ] && [ -s "semgrep.sarif" ]; then
+ echo "sarif-exists=true" >> $GITHUB_OUTPUT
+ echo "Semgrep SARIF file found and not empty"
+ else
+ echo "sarif-exists=false" >> $GITHUB_OUTPUT
+ echo "No Semgrep SARIF file generated or file is empty"
+ fi
+
+ - name: Upload SARIF to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
- if: always()
+ if: steps.check-semgrep-sarif.outputs.sarif-exists == 'true'
with:
sarif_file: semgrep.sarif
- category: sast
- # SCA - Software Composition Analysis (Multi-language)
- sca:
+ # Secrets Scanning - Complementa o Secret Scanning nativo
+ secrets-scan:
runs-on: ubuntu-latest
- needs: setup
- strategy:
- matrix:
- scanner: [trivy, dependency-check]
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- # Scanner Trivy - Melhor para Python, Node.js, Go, etc.
- - name: Run Trivy SCA scan
- if: matrix.scanner == 'trivy'
- uses: aquasecurity/trivy-action@master
- with:
- scan-type: 'fs'
- scan-ref: '.'
- format: 'sarif'
- output: 'trivy-sca.sarif'
- severity: 'CRITICAL,HIGH,MEDIUM'
- ignore-unfixed: false
-
- # Scanner Dependency Check - Melhor para Java, .NET
- - name: Run Dependency Check
- if: matrix.scanner == 'dependency-check'
- uses: dependency-check/Dependency-Check_Action@main
- with:
- project: 'devsecops-project'
- path: '.'
- format: 'SARIF'
- out: 'dependency-check.sarif'
- args: >
- --failOnCVSS 7
- --enableRetired
- --enableExperimental
-
- - name: Upload SCA results
- uses: actions/upload-artifact@v4
- if: always()
- with:
- name: sca-results-${{ matrix.scanner }}
- path: "*.sarif"
- retention-days: 30
-
- - name: Upload to GitHub Security tab
- uses: github/codeql-action/upload-sarif@v3
- if: always()
- with:
- sarif_file: "*.sarif"
- category: sca-${{ matrix.scanner }}
-
- # Secrets Scanning
- secrets:
- runs-on: ubuntu-latest
- needs: setup
+ permissions:
+ security-events: write
+ contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -123,160 +74,105 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_ENABLE_COMMENTS: false
- - name: Run TruffleHog
- uses: trufflesecurity/trufflehog@main
- with:
- path: ./
- base: main
- head: HEAD
- extra_args: --debug --only-verified
-
- # IaC - Infrastructure as Code Security
- iac:
+ # Container Security - Scan da imagem Docker
+ container-scan:
runs-on: ubuntu-latest
- needs: setup
+ permissions:
+ security-events: write
+ contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- - name: Run Trivy IaC scan
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build Docker image
+ id: build
+ run: |
+ echo "Building Docker image..."
+ docker build -t devsecops-app:latest . || {
+ echo "Docker build failed, but continuing with filesystem scan"
+ echo "build-success=false" >> $GITHUB_OUTPUT
+ exit 0
+ }
+ echo "build-success=true" >> $GITHUB_OUTPUT
+ continue-on-error: true
+
+ - name: Run Trivy container scan
+ if: steps.build.outputs.build-success == 'true'
uses: aquasecurity/trivy-action@master
with:
- scan-type: 'config'
- scan-ref: '.'
+ image-ref: 'devsecops-app:latest'
format: 'sarif'
- output: 'trivy-iac.sarif'
- severity: 'CRITICAL,HIGH'
+ output: 'trivy-container.sarif'
+ continue-on-error: true
- - name: Run Checkov
- uses: bridgecrewio/checkov-action@master
- with:
- directory: .
- framework: dockerfile,kubernetes,terraform
- output_format: sarif
- output_file_path: checkov.sarif
-
- - name: Upload IaC results
- uses: actions/upload-artifact@v4
- if: always()
+ - name: Run Trivy filesystem scan (fallback)
+ if: steps.build.outputs.build-success == 'false'
+ uses: aquasecurity/trivy-action@master
with:
- name: iac-results
- path: "*.sarif"
- retention-days: 30
+ scan-type: 'fs'
+ scan-ref: '.'
+ format: 'sarif'
+ output: 'trivy-container.sarif'
+ continue-on-error: true
- - name: Upload to GitHub Security tab
+ - name: Check if SARIF file exists
+ id: check-sarif
+ run: |
+ echo "Files in current directory:"
+ ls -la *.sarif 2>/dev/null || echo "No SARIF files found"
+ if [ -f "trivy-container.sarif" ] && [ -s "trivy-container.sarif" ]; then
+ echo "sarif-exists=true" >> $GITHUB_OUTPUT
+ echo "SARIF file found and not empty"
+ else
+ echo "sarif-exists=false" >> $GITHUB_OUTPUT
+ echo "No SARIF file generated or file is empty"
+ fi
+
+ - name: Upload Trivy results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
- if: always()
+ if: steps.check-sarif.outputs.sarif-exists == 'true'
with:
- sarif_file: "*.sarif"
- category: iac
+ sarif_file: trivy-container.sarif
+ category: container-security
- # DAST - Dynamic Application Security Testing
- dast:
+ # IaC Scanning - Para Dockerfile e configs
+ iac-scan:
runs-on: ubuntu-latest
- needs: setup
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
+ permissions:
+ security-events: write
+ contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- - name: Setup Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Build and start application
- run: |
- docker build -t app-under-test .
- docker run -d --name test-app -p 5000:5000 app-under-test
- sleep 30 # Wait for app to start
-
- - name: Run OWASP ZAP Full Scan
- uses: zaproxy/action-full-scan@v0.10.0
- with:
- target: 'http://localhost:5000'
- rules_file_name: '.zap/rules.tsv'
- cmd_options: '-a -j -m 5 -T 60'
-
- - name: Upload DAST results
- uses: actions/upload-artifact@v4
- if: always()
- with:
- name: dast-results
- path: report_html.html
- retention-days: 30
-
- # Consolidação de resultados para IA
- consolidate-results:
- runs-on: ubuntu-latest
- needs: [sast, sca, secrets, iac]
- if: always()
- steps:
- - name: Download all artifacts
- uses: actions/download-artifact@v4
- with:
- path: all-results/
-
- - name: Consolidate SARIF files
- run: |
- mkdir -p consolidated-sarif
- find all-results/ -name "*.sarif" -exec cp {} consolidated-sarif/ \;
- ls -la consolidated-sarif/
-
- - name: Upload consolidated results
- uses: actions/upload-artifact@v4
- with:
- name: consolidated-security-results
- path: consolidated-sarif/
- retention-days: 30
-
- - name: Create summary comment (prepare for AI integration)
- if: github.event_name == 'pull_request'
- run: |
- echo "# 🔒 Security Scan Results" > security-summary.md
- echo "" >> security-summary.md
- echo "| Scanner | Status | Files Scanned |" >> security-summary.md
- echo "|---------|---------|---------------|" >> security-summary.md
-
- # Count SARIF files to show scan status
- SAST_FILES=$(find consolidated-sarif/ -name "*semgrep*" | wc -l)
- SCA_FILES=$(find consolidated-sarif/ -name "*trivy*" -o -name "*dependency*" | wc -l)
- IAC_FILES=$(find consolidated-sarif/ -name "*iac*" -o -name "*checkov*" | wc -l)
-
- echo "| SAST (Semgrep) | ✅ | $SAST_FILES |" >> security-summary.md
- echo "| SCA (Trivy/DepCheck) | ✅ | $SCA_FILES |" >> security-summary.md
- echo "| IaC (Trivy/Checkov) | ✅ | $IAC_FILES |" >> security-summary.md
- echo "| Secrets (Gitleaks) | ✅ | N/A |" >> security-summary.md
- echo "" >> security-summary.md
- echo "**Next Step**: AI agent will analyze findings and suggest fixes 🤖" >> security-summary.md
-
- - name: Upload summary
- uses: actions/upload-artifact@v4
- if: github.event_name == 'pull_request'
+ - name: Run Trivy IaC scan
+ uses: aquasecurity/trivy-action@master
with:
- name: security-summary
- path: security-summary.md
- retention-days: 7
+ scan-type: 'config'
+ scan-ref: '.'
+ format: 'sarif'
+ output: 'trivy-iac.sarif'
+ continue-on-error: true
- # Preparação para trigger de IA (placeholder)
- trigger-ai-analysis:
- runs-on: ubuntu-latest
- needs: consolidate-results
- if: always() && github.event_name == 'pull_request'
- steps:
- - name: Trigger AI analysis workflow
+ - name: Check if IaC SARIF file exists
+ id: check-iac-sarif
run: |
- echo "🤖 Triggering AI analysis for PR ${{ github.event.number }}"
- echo "This step will trigger the AI agent workflow in the future"
- echo "AI will analyze consolidated SARIF files and create fix suggestions"
-
- # Placeholder para repository dispatch que vai trigger a IA
- - name: Repository Dispatch to AI Workflow
- uses: peter-evans/repository-dispatch@v3
+ echo "Files in current directory:"
+ ls -la *.sarif 2>/dev/null || echo "No SARIF files found"
+ if [ -f "trivy-iac.sarif" ] && [ -s "trivy-iac.sarif" ]; then
+ echo "sarif-exists=true" >> $GITHUB_OUTPUT
+ echo "IaC SARIF file found and not empty"
+ else
+ echo "sarif-exists=false" >> $GITHUB_OUTPUT
+ echo "No IaC SARIF file generated or file is empty"
+ fi
+
+ - name: Upload IaC results to GitHub Security tab
+ uses: github/codeql-action/upload-sarif@v3
+ if: steps.check-iac-sarif.outputs.sarif-exists == 'true'
with:
- token: ${{ secrets.GITHUB_TOKEN }}
- event-type: security-scan-completed
- client-payload: |
- {
- "pr_number": "${{ github.event.number }}",
- "sha": "${{ github.sha }}",
- "artifacts": ["consolidated-security-results", "security-summary"]
- }
\ No newline at end of file
+ sarif_file: trivy-iac.sarif
+ category: iac
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 0398402..393112f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,35 +1,49 @@
-FROM frolvlad/alpine-python3
+FROM python:3.11-alpine
ENV API_SERVER_HOME=/opt/www
WORKDIR "$API_SERVER_HOME"
+
+# Install system dependencies first
+RUN apk update && apk add --no-cache \
+ gcc \
+ libffi-dev \
+ linux-headers \
+ musl-dev \
+ python3-dev \
+ && rm -rf /var/cache/apk/*
+
+# Copy requirements and install Python dependencies
COPY "./requirements.txt" "./"
COPY "./app/requirements.txt" "./app/"
-COPY "./config.py" "./"
COPY "./tasks" "./tasks"
+# Handle optional dependencies and install everything in one RUN
ARG INCLUDE_POSTGRESQL=false
ARG INCLUDE_UWSGI=false
-RUN apk add --no-cache --virtual=.build_dependencies musl-dev gcc python3-dev libffi-dev linux-headers && \
- cd /opt/www && \
- pip install -r tasks/requirements.txt && \
- invoke app.dependencies.install && \
- ( \
- if [ "$INCLUDE_POSTGRESQL" = 'true' ]; then \
- apk add --no-cache libpq && \
- apk add --no-cache --virtual=.build_dependencies postgresql-dev && \
- pip install psycopg2 ; \
- fi \
- ) && \
- ( if [ "$INCLUDE_UWSGI" = 'true' ]; then pip install uwsgi ; fi ) && \
- rm -rf ~/.cache/pip && \
- apk del .build_dependencies
+RUN pip install --no-cache-dir --upgrade pip && \
+ pip install --no-cache-dir -r requirements.txt && \
+ pip install --no-cache-dir -r app/requirements.txt && \
+ pip install --no-cache-dir -r tasks/requirements.txt && \
+ if [ "$INCLUDE_POSTGRESQL" = 'true' ]; then \
+ apk add --no-cache postgresql-dev libpq && \
+ pip install --no-cache-dir psycopg2-binary; \
+ fi && \
+ if [ "$INCLUDE_UWSGI" = 'true' ]; then \
+ pip install --no-cache-dir uwsgi; \
+ fi
+
+# Copy application code and setup
COPY "./" "./"
+COPY "./config.py" "./"
-RUN chown -R nobody "." && \
- if [ ! -e "./local_config.py" ]; then \
- cp "./local_config.py.template" "./local_config.py" ; \
- fi
+RUN if [ ! -e "./local_config.py" ]; then \
+ cp "./local_config.py.template" "./local_config.py"; \
+ fi && \
+ adduser -D -s /bin/sh appuser && \
+ chown -R appuser:appuser "$API_SERVER_HOME"
+
+USER appuser
+EXPOSE 5000
-USER nobody
-CMD [ "invoke", "app.run", "--no-install-dependencies", "--host", "0.0.0.0" ]
+CMD [ "python", "-m", "flask", "run", "--host", "0.0.0.0", "--port", "5000" ]
diff --git a/README.md b/README.md
index f5e9209..415047f 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,247 @@
-# Implementação de Segurança na Pipeline
-
+# 🛡️ Esteira de Segurança Automatizada - DevSecOps
-Esta documentação reune informações sobre as ferramentas de segurança que estão sendo usadas na pipeline de integração contínua via GitHub Actions para verificar a segurança do código-fonte e da aplicação. É realizado os seguintes tipos de testes de forma automatizada: SAST, SCA, DAST, Secrets Scan e IaC Scan. O projeto utilizado para os testes é uma API construida em Python utilizando o framework Flask.
-
-## Diagrama de arquitetura
-
+