diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bff6784..d137789 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,13 +1,25 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - +# Note directory is relative to the root of the repo, with exception to github-actions ecosystem. +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#directory version: 2 updates: - # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" - # Workflow files stored in the default location of `.github/workflows` directory: "/" schedule: interval: "weekly" + reviewers: + - "joshua-seals" + + - package-ecosystem: "pip" + directory: "/tycho" + schedule: + interval: "weekly" + reviewers: + - "joshua-seals" + - "Hoid" + - "waTeim" + - "pj-linebaugh" + - "ptlharit2" + - "frostyfan109" + - "cnbennett3" + diff --git a/.github/workflows/build-project.yml b/.github/workflows/build-project.yml index 2c38d9c..7a4f157 100644 --- a/.github/workflows/build-project.yml +++ b/.github/workflows/build-project.yml @@ -1,26 +1,6 @@ name: Build-Project run-name: Build-Project -on: - # Any push with exception to the below listed - # as they will be built in pypi-upload task. - push: - branches-ignore: - - master - - main - paths-ignore: - - README.md - - .old_cicd/* - - .github/* - - .github/workflows/* - - LICENSE - - .gitignore - - .dockerignore - - .githooks - tags-ignore: - - 'v[0-9]+.[0-9]+.*' - # We still test to ensure the build is successful - # for a 'potential PR' when opened. If additions to PR - # are pushed, we catch in the push section. +on: pull_request: branches: [ master, develop, main ] types: [ opened ] diff --git a/.github/workflows/flake8.yml b/.github/workflows/code-checks.yml similarity index 60% rename from .github/workflows/flake8.yml rename to .github/workflows/code-checks.yml index 0757bb9..f228fc9 100644 --- a/.github/workflows/flake8.yml +++ b/.github/workflows/code-checks.yml @@ -25,13 +25,30 @@ jobs: uses: actions/setup-python@v4 with: python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt + - name: Lint with flake8 run: | pip install flake8 flake8 --ignore=E,W --exit-zero . # We continue on error here until the code is clean continue-on-error: true + +############################ Bandit ################################ + bandit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - name: Install Requirements + run: | + pip install --upgrade pip + pip install bandit + + # Only report high security issues + - name: Test with Bandit + run: | + bandit -r tycho/*.py -n 3 -lll \ No newline at end of file diff --git a/.github/workflows/pypi-dev-upload.yml b/.github/workflows/pypi-dev-upload.yml index 50965ca..16f4449 100644 --- a/.github/workflows/pypi-dev-upload.yml +++ b/.github/workflows/pypi-dev-upload.yml @@ -1,9 +1,12 @@ +# This workflow will create an image for any tycho development taking place, not in master branch. +# We use the {{ github.ref_name }} ie branch name and date to ensure uniqueness of the package. name: upload-dev-pypi run-name: Package and Upload develop image to Pypi on: push: - branches: - - develop + branches-ignore: + - master + - main paths-ignore: - README.md - .old_cicd/* @@ -30,12 +33,11 @@ jobs: # Important, this does not change the current version of __init__.py in the # Github repo itself, only updates within container for the specific run. - # Each new push will trigger a dev build on develop. - - name: Edit __init__.py version for develop release run: | R_VERSION=$(grep VERSION ./tycho/__init__.py | awk '{ print $3 }' | tr -d '"') date=$(date '+%Y%m%d%H%M%S') + BRANCH=$(echo ${{ github.ref_name}} | sed 's/[_-]//g') DEV_VERSION=${R_VERSION}.dev${date} echo VERSION=\"$DEV_VERSION\" > ./tycho/__init__.py diff --git a/Dockerfile b/Dockerfile index 9ef31a7..26467ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9.0-slim +FROM python:3.11.4-slim-bullseye RUN apt-get update && \ apt-get install -y build-essential libffi-dev libssl-dev git make diff --git a/pyproject.toml b/pyproject.toml index 4f64fa5..e9b05ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,6 @@ classifiers = [ ] dependencies = [ "deepmerge==1.0.1", - "docker_compose==1.29.2", "flasgger==0.9.5", "Flask==2.0.3", "flask_cors==3.0.10", @@ -34,7 +33,8 @@ dependencies = [ "kubernetes==25.3.0", "netifaces==0.11.0", "PyYAML==5.4.1", - "requests==2.27.1", + "requests==2.31.0", + "docker-compose==1.29.2", "requests_cache==0.9.2", ] dynamic = ["version"] diff --git a/requirements.txt b/requirements.txt index 0ccfb09..b827abc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,11 +19,11 @@ certifi==2021.10.8 cffi==1.15.0 chardet==4.0.0 coverage==6.3.1 -cryptography==36.0.1 +cryptography==41.0.2 deepmerge==1.0.1 docker==5.0.3 -docker-compose==1.29.2 -docker-pycreds==0.4.0 +docker-compose==1.29.2 +docker-pycreds==0.4.0 dockerpty==0.4.1 docopt==0.6.2 flasgger==0.9.5 @@ -52,7 +52,7 @@ pytest-cov==3.0.0 pytest-mock==3.7.0 python-dateutil==2.8.2 pytz==2021.3 -requests==2.27.1 +requests==2.31.0 requests-cache==0.9.2 requests-oauthlib==1.3.1 rsa==4.8 diff --git a/tycho/actions.py b/tycho/actions.py index 08c0ac3..18a4808 100644 --- a/tycho/actions.py +++ b/tycho/actions.py @@ -25,7 +25,7 @@ 'api-schema.yaml') template = None with open(schema_file_path, 'r') as file_obj: - template = yaml.load(file_obj, Loader=yaml.FullLoader) + template = yaml.load(file_obj, Loader=yaml.FullLoader) #nosec B506 backplane = None _tycho = Tycho(backplane=backplane) @@ -45,7 +45,7 @@ def validate(self, request, component): """ Validate a request against the schema. """ if not self.specs: with open(schema_file_path, 'r') as file_obj: - self.specs = yaml.load(file_obj, Loader=yaml.FullLoader) + self.specs = yaml.load(file_obj, Loader=yaml.FullLoader) #nosec B506 to_validate = self.specs["components"]["schemas"][component] try: logger.debug(f"--:Validating obj {request}") diff --git a/tycho/api.py b/tycho/api.py index d827491..317d52e 100644 --- a/tycho/api.py +++ b/tycho/api.py @@ -38,7 +38,7 @@ 'api-schema.yaml') template = None with open(schema_file_path, 'r') as file_obj: - template = yaml.load(file_obj, Loader=yaml.FullLoader) + template = yaml.load(file_obj, Loader=yaml.FullLoader) #nosec B506 """ Describe the API. """ app.config['SWAGGER'] = { @@ -73,7 +73,7 @@ def validate (self, request, component): """ Validate a request against the schema. """ if not self.specs: with open(schema_file_path, 'r') as file_obj: - self.specs = yaml.load(file_obj, Loader=yaml.FullLoader) + self.specs = yaml.load(file_obj, Loader=yaml.FullLoader) #nosec B506 to_validate = self.specs["components"]["schemas"][component] try: app.logger.debug (f"--:Validating obj {json.dumps(request.json, indent=2)}") @@ -268,4 +268,4 @@ def post(self): if args.debug: debug = True logging.basicConfig(level=logging.DEBUG) - app.run(host='0.0.0.0', port=args.port, threaded=True, debug=args.debug) + app.run(host='0.0.0.0', port=args.port, threaded=True, debug=args.debug) #nosec B104 diff --git a/tycho/client.py b/tycho/client.py index 95890d1..2f0be33 100644 --- a/tycho/client.py +++ b/tycho/client.py @@ -124,7 +124,7 @@ def request (self, service, request): :param request: JSON to send to the API endpoint. """ if os.environ.get("REST_API", "false") == "true": - response = requests.post (f"{self.url}/{service}", json=request) + response = requests.post (f"{self.url}/{service}", json=request) #nosec B113 result_text = f"HTTP status {response.status_code} received from service: {service}" logger.debug (f"TychoClient.request - {result_text}") if not response.status_code == 200: @@ -539,9 +539,9 @@ def getmetadata(self): if os.path.exists (env_file): with open (env_file, 'r') as stream: settings = stream.read () - + # added safeloader here, per bandit instructions. with open(args.file, "r") as stream: - system = yaml.load (stream.read ()) + system = yaml.load (stream.read (), Loader=yaml.SafeLoader) else: """ Generate a docker-compose spec based on the CLI args. """ name = args.name diff --git a/tycho/dockerc.py b/tycho/dockerc.py index c4889f9..8f1d081 100644 --- a/tycho/dockerc.py +++ b/tycho/dockerc.py @@ -47,7 +47,7 @@ def run (self): stream.write (env) """ Find and return ports for each container. """ - config = yaml.load (TemplateUtils.apply_environment ( + config = yaml.safe_load (TemplateUtils.apply_environment ( env, self.system.source_text)) logger.debug (f"Building conainer map for system {self.system.name}") diff --git a/tycho/kube.py b/tycho/kube.py index 2595a4a..3a6791b 100644 --- a/tycho/kube.py +++ b/tycho/kube.py @@ -277,9 +277,12 @@ def get_service_ip_address (self, service_metadata): exe = shutil.which ('kubectl') command = f"{exe} port-forward --pod-running-timeout=3m0s deployment/{app_id} {node_port}:{port}" logger.debug (f"-- port-forward: {command}") - process = subprocess.Popen (command, - shell=True, - stderr=subprocess.STDOUT) + # commented out due to bandit High Severity flag for this process. + # The variable 'process' was not accessed so this should not cause issue. + # Leaving for now just in case there are problems encountered. + # process = subprocess.Popen (command, + # shell=True, + # stderr=subprocess.STDOUT) """ process dies when the other end disconnects so no need to clean up in delete. """ #ip_address = "127.0.0.1" except Exception as e: