Hardening a Python Application
How to harden a Python application
- Find the upstream project source (i.e. github) and identify the desired release and Python version.
- 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. - Clone https://repo1.dso.mil/dsop/container-hardening-tools/proof-of-concept/resource_scripts
- Copy your project's
./requirements_files/pip-packages.txt
to the resource_scripts./requirements_files/pip-packages.txt
- 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
- The
generate_hardening_manifest.py
script will readpip-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
. - Open
./hardening_manifest/hardening_manifest.yaml
and copy the resources to your project'shardening_manifest.yaml
. - Review the resource list for duplicates, correct OS/arch and Python version.
- Use the fetch tool to read your project's hardening_manifest.yaml, download the resources and validate checksums.
- Update your Dockerfile to COPY all
*.whl
and*.tar.gz
files into the image build, and then usepip
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