Skip to content

Hardening a Python Application

How to harden a Python application

  1. Find the upstream project source (i.e. github) and identify the desired release and Python version.
  2. Pull out the requirements.txt from the upstream project source and copy to your project: ./requirements_files/pip-packages.txt with no comments or whitespace at the top of the file.
  3. Clone https://repo1.dso.mil/dsop/container-hardening-tools/proof-of-concept/resource_scripts
  4. Copy your project's ./requirements_files/pip-packages.txt to the resource_scripts ./requirements_files/pip-packages.txt
  5. Mount resource_scripts into an Iron Bank Python image matching the application release's required Python version:
    docker run -ti --rm --entrypoint=python -w /app -v $PWD:/app registry1.dso.mil/ironbank/opensource/python/python39:latest generate_hardening_manifest.py -p
    
  6. The generate_hardening_manifest.py script will read pip-packages.txt and download .whl or .tar.gz files from PyPi that match the Iron Bank image's architecture and Python version, and will finally generate a manifest at ./hardening_manifest/hardening_manifest.yaml.
  7. Open ./hardening_manifest/hardening_manifest.yaml and copy the resources to your project's hardening_manifest.yaml.
  8. Review the resource list for duplicates, correct OS/arch and Python version.
  9. Use the fetch tool to read your project's hardening_manifest.yaml, download the resources and validate checksums.
  10. Update your Dockerfile to COPY all *.whl and *.tar.gz files into the image build, and then use pip to install:
    ARG PACKAGE_DIR="."
    COPY ["${PACKAGE_DIR}/*.whl", "${PACKAGE_DIR}/*.tar.gz", "/pip_pkgs/"]
    RUN pip install --no-index --no-deps /pip_pkgs/*.whl /pip_pkgs/*.tar.gz
    

Note (Pulling in dependancies with Pip)

IronBank has implemented a new method of pulling in Python dependancies. PyPi is now mirrored by our Nexus proxy. Instead of collecting and individually placing dependancy files in the hardening manifest, developers are now able to use a requirements.txt file and install with the pip command just as you would locally.

For individuals using other sources (private PyPi or anaconda) to pull python packages, you will need to revert back to using the older method which would require you individually collect the packages and place them in the hardening manifest.

Testing

Test executing the entrypoint (if applicable), comparing its output to the upstream image. If the image provides multiple tools, then attach to a running container and execute each tool. For either case, we want to verify that each tool/app works without exiting on missing Python dependencies.

If there are any missing dependencies, search PyPi for your package version, arch and Python version, always preferring .whl files instead of source .tar.gz files. Update your hardening_manifest.yaml, run fetch, and rebuild. Iterate until there are no more errors, then push your branch to repo one where you can track build progress.

Once your build completes you can merge to development and start working on justifications if necessary.

Example Projects

  • Molecule: https://repo1.dso.mil/dsop/opensource/molecule/molecule
  • Odoo: https://repo1.dso.mil/dsop/opensource/odoo/odoo