From 97325b5a282cbf8e582b7cd459fcc00594a48cbf Mon Sep 17 00:00:00 2001 From: Patrick Foley Date: Fri, 29 Sep 2023 14:41:55 -0700 Subject: [PATCH] WIP: CI Scans (#873) * Initial scans commit for bandit, hadolint, trivy Signed-off-by: Patrick Foley * Address bandit scan results Signed-off-by: Patrick Foley * Fix Trivy action Signed-off-by: Patrick Foley * Fix linting Signed-off-by: Patrick Foley * Add Coverity Badge Signed-off-by: Patrick Foley * Update Hadolint threshold to flag errors only Signed-off-by: Patrick Foley * Update Hadolint threshold to flag errors only Signed-off-by: Patrick Foley --------- Signed-off-by: Patrick Foley --- .github/workflows/scans.yml | 30 +++++++++++++++++++ .github/workflows/trivy.yml | 29 ++++++++++++++++++ README.md | 6 +++- .../experimental/utilities/metaflow_utils.py | 7 +++-- openfl/interface/tutorial.py | 2 +- openfl/interface/workspace.py | 6 ++-- .../interface_serializer/dill_serializer.py | 4 +-- openfl/transport/grpc/aggregator_server.py | 2 +- openfl/utilities/ca/ca.py | 4 +-- openfl/utilities/ca/downloader.py | 3 +- openfl/utilities/workspace.py | 2 +- 11 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/scans.yml create mode 100644 .github/workflows/trivy.yml diff --git a/.github/workflows/scans.yml b/.github/workflows/scans.yml new file mode 100644 index 0000000000..93d0d75425 --- /dev/null +++ b/.github/workflows/scans.yml @@ -0,0 +1,30 @@ +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: Security Scans + +on: + pull_request: + branches: [ develop ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.8 + uses: actions/setup-python@v3 + with: + python-version: "3.8" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install . + - name: Hadolint Dockerfile Scan + run: | + docker run -v ${PWD}/openfl-docker:/openfl-docker --rm -i hadolint/hadolint hadolint -t error /openfl-docker/Dockerfile.base diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml new file mode 100644 index 0000000000..8618bdae16 --- /dev/null +++ b/.github/workflows/trivy.yml @@ -0,0 +1,29 @@ +name: build +on: + push: + branches: + - main + pull_request: +jobs: + build: + name: Build + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Build an image from Dockerfile + run: | + docker build -t docker.io/securefederatedai/openfl:${{ github.sha }} -f openfl-docker/Dockerfile.base . + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + image-ref: 'docker.io/securefederatedai/openfl:${{ github.sha }}' + format: 'sarif' + output: 'trivy-results.sarif' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: 'trivy-results.sarif' diff --git a/README.md b/README.md index 0db6182bb2..ea4b780fc2 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,12 @@ [](https://join.slack.com/t/openfl/shared_invite/zt-ovzbohvn-T5fApk05~YS_iZhjJ5yaTw) [![License](https://img.shields.io/badge/License-Apache%202.0-brightgreen.svg)](https://opensource.org/licenses/Apache-2.0) [![Citation](https://img.shields.io/badge/cite-citation-brightgreen)](https://arxiv.org/abs/2105.06413) -[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/openfl/blob/develop/openfl-tutorials/interactive_api/numpy_linear_regression/workspace/SingleNotebook.ipynb) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6599/badge)](https://bestpractices.coreinfrastructure.org/projects/6599) + + Coverity Scan Build Status + +[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/intel/openfl/blob/develop/openfl-tutorials/interactive_api/numpy_linear_regression/workspace/SingleNotebook.ipynb) OpenFL is a Python 3 framework for Federated Learning. OpenFL is designed to be a _flexible_, _extensible_ and _easily learnable_ tool for data scientists. OpenFL is hosted by The Linux Foundation, aims to be community-driven, and welcomes contributions back to the project. diff --git a/openfl/experimental/utilities/metaflow_utils.py b/openfl/experimental/utilities/metaflow_utils.py index 9e26d73409..9dccca1487 100644 --- a/openfl/experimental/utilities/metaflow_utils.py +++ b/openfl/experimental/utilities/metaflow_utils.py @@ -25,7 +25,8 @@ from metaflow.task import MetaDatum import fcntl import hashlib -from dill.source import getsource +from dill.source import getsource # nosec +# getsource only used to determine structure of FlowGraph from typing import TYPE_CHECKING if TYPE_CHECKING: from openfl.experimental.interface import FLSpec @@ -62,7 +63,9 @@ def __init__(self, name): self.name = name def __enter__(self): - lock_id = hashlib.new('md5', self.name.encode("utf8"), usedforsecurity=False).hexdigest() + lock_id = hashlib.new('md5', self.name.encode("utf8"), + usedforsecurity=False).hexdigest() # nosec + # MD5sum used for concurrency purposes, not security self.fp = open(f"/tmp/.lock-{lock_id}.lck", "wb") fcntl.flock(self.fp.fileno(), fcntl.LOCK_EX) diff --git a/openfl/interface/tutorial.py b/openfl/interface/tutorial.py index 634e9b107f..85a0cb3f66 100644 --- a/openfl/interface/tutorial.py +++ b/openfl/interface/tutorial.py @@ -30,7 +30,7 @@ def start(ip, port): """Start the Jupyter Lab from the tutorials directory.""" from os import environ from os import sep - from subprocess import check_call + from subprocess import check_call # nosec from sys import executable from openfl.interface.cli_helper import TUTORIALS diff --git a/openfl/interface/workspace.py b/openfl/interface/workspace.py index e28e6534f5..1ee747ca7b 100644 --- a/openfl/interface/workspace.py +++ b/openfl/interface/workspace.py @@ -3,7 +3,7 @@ """Workspace module.""" import os -import subprocess +import subprocess # nosec import sys from pathlib import Path from typing import Tuple, Union @@ -86,7 +86,7 @@ def create_(prefix, template): def create(prefix, template): """Create federated learning workspace.""" from os.path import isfile - from subprocess import check_call + from subprocess import check_call # nosec from sys import executable from openfl.interface.cli_helper import print_tree @@ -196,7 +196,7 @@ def import_(archive): from os.path import basename from os.path import isfile from shutil import unpack_archive - from subprocess import check_call + from subprocess import check_call # nosec from sys import executable archive = Path(archive).absolute() diff --git a/openfl/plugins/interface_serializer/dill_serializer.py b/openfl/plugins/interface_serializer/dill_serializer.py index 5b3aaaa42e..f4bb9ffd58 100644 --- a/openfl/plugins/interface_serializer/dill_serializer.py +++ b/openfl/plugins/interface_serializer/dill_serializer.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 """Dill serializer plugin.""" -import dill +import dill # nosec from .serializer_interface import Serializer @@ -24,4 +24,4 @@ def serialize(object_, filename): def restore_object(filename): """Load and deserialize an object.""" with open(filename, 'rb') as f: - return dill.load(f) + return dill.load(f) # nosec diff --git a/openfl/transport/grpc/aggregator_server.py b/openfl/transport/grpc/aggregator_server.py index fa71d98c9d..39fde16445 100644 --- a/openfl/transport/grpc/aggregator_server.py +++ b/openfl/transport/grpc/aggregator_server.py @@ -83,7 +83,7 @@ def validate_collaborator(self, request, context): if not self.aggregator.valid_collaborator_cn_and_id( common_name, collaborator_common_name): # Random delay in authentication failures - sleep(5 * random()) + sleep(5 * random()) # nosec context.abort( StatusCode.UNAUTHENTICATED, f'Invalid collaborator. CN: |{common_name}| ' diff --git a/openfl/utilities/ca/ca.py b/openfl/utilities/ca/ca.py index f5dace0be7..1ff88c5742 100644 --- a/openfl/utilities/ca/ca.py +++ b/openfl/utilities/ca/ca.py @@ -9,11 +9,11 @@ import sys import shutil import signal -import subprocess +import subprocess # nosec import time from logging import getLogger from pathlib import Path -from subprocess import check_call +from subprocess import check_call # nosec from click import confirm diff --git a/openfl/utilities/ca/downloader.py b/openfl/utilities/ca/downloader.py index 10b9465b79..9331d1fd4a 100644 --- a/openfl/utilities/ca/downloader.py +++ b/openfl/utilities/ca/downloader.py @@ -67,5 +67,6 @@ def _download(url, prefix, confirmation): if confirmation: confirm('CA binaries will be downloaded now', default=True, abort=True) name = url.split('/')[-1] - urllib.request.urlretrieve(url, f'{prefix}/{name}') + # nosec: private function definition with static urls + urllib.request.urlretrieve(url, f'{prefix}/{name}') # nosec shutil.unpack_archive(f'{prefix}/{name}', f'{prefix}/step') diff --git a/openfl/utilities/workspace.py b/openfl/utilities/workspace.py index bf392e0259..c1561b726e 100644 --- a/openfl/utilities/workspace.py +++ b/openfl/utilities/workspace.py @@ -10,7 +10,7 @@ import time from contextlib import contextmanager from pathlib import Path -from subprocess import check_call +from subprocess import check_call # nosec from sys import executable from typing import Optional from typing import Tuple