Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/scripts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__/
58 changes: 58 additions & 0 deletions .github/scripts/repair-scrub-sarif.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""Temporarily repair SARIF generated by nasa-scrub 3.0.

Remove this script once https://github.com/nasa/scrub/issues/118 is fixed and
the workflow no longer pins an affected nasa-scrub version.
"""

import argparse
import json
from pathlib import Path


SARIF_SCHEMA_2_1_0 = "https://json.schemastore.org/sarif-2.1.0.json"


def repair_sarif_file(sarif_file: Path) -> bool:
with sarif_file.open() as file:
sarif = json.load(file)

changed = False
if sarif.get("$schema") != SARIF_SCHEMA_2_1_0:
sarif["$schema"] = SARIF_SCHEMA_2_1_0
changed = True

for run in sarif.get("runs", []):
tool = run.get("tool")
if not isinstance(tool, dict) or "rules" not in tool:
continue

driver = tool.setdefault("driver", {})
if "rules" not in driver:
driver["rules"] = tool["rules"]
elif isinstance(driver["rules"], list) and isinstance(tool["rules"], list):
driver["rules"].extend(tool["rules"])

del tool["rules"]
changed = True

if changed:
with sarif_file.open("w") as file:
json.dump(sarif, file, indent=2)
file.write("\n")

return changed


def main() -> None:
parser = argparse.ArgumentParser(description="Repair nasa-scrub SARIF output for SonarQube import.")
parser.add_argument("results_dir", type=Path)
args = parser.parse_args()

for sarif_file in args.results_dir.glob("*_stripped.sarif"):
if repair_sarif_file(sarif_file):
print(f"Repaired {sarif_file}")


if __name__ == "__main__":
main()
175 changes: 138 additions & 37 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
@@ -1,73 +1,174 @@
name: Security Scan
# AMMOS OSS Security Scan
# (internal) docs - https://wiki.jpl.nasa.gov/pages/viewpage.action?spaceKey=AmmosArch&title=Code+Vulnerability+Scanning+Set+Up+for+AMMOS+Open+Source+Software
name: 'Security Scan'

on:
pull_request:
branches:
- develop
- dev-[0-9]+.[0-9]+.[0-9]+
push:
branches:
- develop
tags:
- v*
- 'v*'
pull_request:
branches:
- develop
- 'dev-[0-9]+.[0-9]+.[0-9]+'
schedule:
- cron: '42 2 * * 0' # weekly cron scan
workflow_dispatch:

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
name: Analyze (${{ matrix.language }})
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
actions: read
contents: write
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read

strategy:
fail-fast: false
matrix:
language: ["java", "javascript"]

include:
- language: actions
build-mode: none
- language: java-kotlin
build-mode: autobuild
- language: javascript-typescript
build-mode: none
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
fetch-depth: 0

# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba #4.35.5
with:
languages: ${{ matrix.language }}
queries: +security-extended
tools: latest
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: "temurin"
java-version: "21"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
with:
# This action defaults to matching on "main" and "master" as the branches allowed to write to the cache
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
- name: Build
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- name: Run manual build steps
if: matrix.build-mode == 'manual'
shell: bash
run: |
./gradlew testClasses
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
- name: NASA Scrub
uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba #4.35.5
with:
category: '/language:${{matrix.language}}'
output: ../results

# This step is required by AMMOS to remove malformed data from the CodeQL output
# It may be possible to remove in future iterations
- name: Post-Process Output
run: |
python3 -m pip install nasa-scrub
python3 -m pip install nasa-scrub==3.0

results_dir=`realpath ${{ github.workspace }}/../results`
sarif_files=`find $results_dir -name '*.sarif'`

for sarif_file in $sarif_files
do
output_file="$results_dir/$(basename $sarif_file .sarif).scrub"
python3 -m scrub.tools.parsers.translate_results $sarif_file $output_file ${{ github.workspace }} scrub
output_file="$results_dir/$(basename $sarif_file .sarif)_stripped.sarif"

python3 -m scrub.tools.parsers.translate_results $sarif_file $output_file ${{ github.workspace }} sarifv2.1.0
done

python3 -m scrub.tools.parsers.csv_parser $results_dir
# TEMPORARY WORKAROUND: remove this once nasa-scrub emits valid SARIF 2.1.0.
# https://github.com/nasa/scrub/issues/118
python3 .github/scripts/repair-scrub-sarif.py "$results_dir"
# END TEMPORARY WORKAROUND

echo "RESULTS_DIR=$results_dir" >> $GITHUB_ENV
- name: Upload Security Scan Results
uses: actions/upload-artifact@v7

# This step makes the analysis artifacts available for download
# This can be helpful for debugging and archive purposes
- name: Upload Artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1
with:
name: Security Scan Results - ${{ matrix.language }}
name: codeql-artifacts-${{ matrix.language }}
path: ${{ env.RESULTS_DIR }}

sonar:
name: Build Java & Run SonarQube Scan
needs: analyze
runs-on: ubuntu-latest
# PRs for forks can't use secrets, can't upload to Sonar
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
permissions:
actions: read
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
fetch-depth: 0

- name: Download CodeQL Artifacts
uses: actions/download-artifact@v4
with:
pattern: codeql-artifacts-*
path: codeql-results

- name: collect stripped .sarif file paths
shell: bash
run: |
echo "downloaded CodeQL artifact files:"
find "${{ github.workspace }}/codeql-results" -type f | sort

sarif_paths="$(find "${{ github.workspace }}/codeql-results" -name '*_stripped.sarif' -type f | paste -sd, -)"
echo "sarif paths: $sarif_paths"
test -n "$sarif_paths"
echo "SARIF_REPORT_PATHS=$sarif_paths" >> "$GITHUB_ENV"

- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: "temurin"
java-version: "21"

- name: Setup Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # 5.0.2
with:
# This action defaults to matching on "main" and "master" as the branches allowed to write to the cache
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}

# PlanDev Sonar scans are run with the sonarqube gradle plugin instead of the Sonar GH action
# this allows discovery + analysis of build artifacts via normal Gradle build process instead of complex Sonar config
- name: Build and run Sonar scan
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: >
./gradlew build sonar
-Dsonar.verbose=true
-Dsonar.gradle.scanAll=true
-Dsonar.sarifReportPaths="${{ env.SARIF_REPORT_PATHS }}"
16 changes: 16 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
id 'com.github.ben-manes.versions' version '0.47.0'
id 'org.sonarqube' version '7.3.0.8198'
}

task archiveDeployment(type: Tar) {
Expand All @@ -21,6 +22,13 @@ configure(subprojects) {
}())
}

sonar {
properties {
property "sonar.projectKey", "NASA-AMMOS_aerie"
property "sonar.organization", "nasa-ammos"
}
}

subprojects {
apply plugin: 'com.github.ben-manes.versions'

Expand All @@ -42,3 +50,11 @@ subprojects {
options.addStringOption('Xdoclint:none', '-quiet')
}
}

// config for Sonar code scanning - see .github/workflows/security-scan.yml
sonar {
properties {
property "sonar.projectKey", "NASA-AMMOS_aerie"
property "sonar.organization", "nasa-ammos"
}
}
17 changes: 17 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Project config file for SonarQube scans (run via GH actions)

sonar.projectKey=NASA-AMMOS_aerie
sonar.organization=nasa-ammos

# name and version displayed in the SonarCloud UI.
sonar.projectName=plandev
sonar.projectVersion=4.2.1

# supported python versions
sonar.python.version=3.7, 3.8, 3.9, 3.10, 3.11, 3.12

# Path of sources to analyze relative to the sonar-project.properties file
#sonar.sources=.

# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
Loading