Agent installation guide
Overview
This guide offers examples for using Contrast Security’s Python agent with Docker. We encourage you to take this guide, make it your own, and distribute it to teams who both need to instrument Python applications and manage them through Docker.
The main portion of the guide details the most popular methods customers use to instrument Python applications contained in Docker and see security data in Contrast.
There is also a lab section that describes how to instrument a sample python application called PyGoat. It’s a good way to learn before proceeding with your own applications. You can instrument PyGoat with Contrast and see security data for this application in Contrast using the source code samples section at the end of this guide.
Main steps
Update the application’s Dockerfile:
- Add the Contrast Python agent
- Configure the agent
- Add authentication credentials for your environment
Instrument your application
Supported technologies
Before you begin, please be sure Contrast supports your preferred tools and environments for Python: Supported technologies for the Python agent
This guide assumes you have:
- Some familiarity with DevOps practices and how Docker works
- Access to the PyPI repository for the Contrast agent
The information to instrument applications with the Python agent and see results in Contrast:
Install the Python agent
Verify that that a C compiler and C standard library headers are available on the system where you are installing the agent. Package names may differ across platforms but installing your platform's version of build-essential should cover most of the prerequisites.
Instructions
To begin, update the Dockerfile for your application.
1) Add the Contrast Python agent
Here are two options to add the Contrast agent and basic configuration to a Docker image. Choose the one that works best for you.
Option 1: Add to the Dockerfile
In this approach, you add the Contrast agent to the application’s Dockerfile. You can add the most recent agent:
RUN pip install contrast-agent
OR target a specific version:
RUN pip install contrast-agent==5.17.1
Example: Dockerfile configuration
FROM python:3.11.0b1-buster
# set work directory
WORKDIR /app
# dependencies for psycopg2
RUN apt-get update && apt-get install --no-install-recommends -y dnsutils libpq-dev python3-dev\
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Install the Contrast agent
RUN pip install -U contrast-agent
# Copy the agent configuration file
COPY ./contrast_security.yaml /etc/contrast/contrast_security.yaml
# Install dependencies
RUN python -m pip install --no-cache-dir pip==22.0.4
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# copy project
COPY . /app/
# install pygoat
RUN python3 /app/manage.py migrate
WORKDIR /app/pygoat/
EXPOSE 8000
CMD ["contrast-python-run","--","/usr/local/bin/python","/app/manage.py","runserver","0.0.0.0:8000"]
Option 2: Add to the requirements.txt
In this approach, you add the agent to the requirements.txt file. To do this:
- Add the Contrast agent to the application’s requirements.txt file. Specify the agent version, if desired.
- Add the requirements install to the docker file if not already present.
Example: adding the agent to requirements.txt
contrast-agent==8.4.0
pip install -U -r requirements.txt
Manual middleware configuration is no longer recommended. Instead, you should run your application with the contrast-python-run
command, which automatically detects and enables framework-specific instrumentation. See Contrast Runner for more information.
For rarer cases where manual middleware configuration is still required, instructions are listed here: Configure middleware
2) Configure the agent
There are different values you can use to configure Contrast agents. This is the order of precedence, and each level overrides the next: 1 is highest.
- Corporate rule (e.g., expired license overrides assess.enable)
- Environment variable value
- YAML configuration file value
- Contrast UI value
- Default value
Order of precedence is explained more here: Order of precedence
We recommend a mixed approach:
- Keep the common configuration in the YAML file so it can be placed in the base image.
- Use environment variables for authentication and application-specific settings.
Common configuration
This approach keeps a core set of configurations in the YAML file. These can be added to a base image and overridden by environment variables when needed.
To do this:
- Add a base service and logging configuration:
agent:
logger:
path: /proc/1/fd/1
level: INFO
progname: Contrast Agent
security_logger:
path: /proc/1/fd/1
level: ERROR
application:
path: /myapp
- Copy the edited YAML file into the base image Dockerfile:
This can be copied into any of the following locations in the container:
<approot>/contrast_security.yaml
<approot>/settings/contrast_security.yaml
/etc/contrast_security.yaml
/etc/contrast/contrast_security.yaml
/etc/contrast/python/contrast_security.yaml
For more options, see the Contrast documentation: Order of precedence
Example:
COPY ./contrast_security.yaml /etc/contrast/contrast_security.yaml
Application-specific configuration
To set an application-specific configuration, use the environment variables in the application’s container. These are some common configuration options. NOTE: use double-underscores here.
For more, see Contrast documentation: Python-specific configuration
-
Application name: Specify the application name reported to Contrast
CONTRAST__APPLICATION__NAME
-
Application group: Specify the application access group for this application during onboarding. NOTE: Application access groups have to be created first in Contrast.
CONTRAST__APPLICATION__GROUP
-
Application tags: Add labels to an application
CONTRAST__APPLICATION__TAGS
-
Server name: Specify the server name reported to Contrast
CONTRAST__SERVER__NAME
-
Server environment: specify in which environment the application is running. Valid values for this configuration are: Development, QA and Production.
CONTRAST__SERVER__ENVIRONMENT
-
Server tag: Add labels to the server
CONTRAST__SERVER__TAG
3) Add authentication credentials for your environment
For the Python agent to send data to Contrast, it needs an API URL and agent credentials for authentication to the server. This is sensitive data and should be treated carefully.
CONTRAST__API__URL=https://app.contrastsecurity.com/Contrast
CONTRAST__API__API_KEY={Your API KEY}
CONTRAST__API__SERVICE_KEY={Your Service key}
CONTRAST__API__USER_NAME={Your agent user}
You can get API values (agent keys) from Contrast or by downloading a YAML file for the Python agent. For more, see Contrast documentation: Find the agent keys
4) Instrument your application
You can now run the application image with Contrast enabled. Contrast will instrument your application during startup and begin reporting security vulnerabilities to Contrast.
You can verify that Contrast is running by checking the container log. You should see messages similar to the following:
2024-06-05 15:15:50 [info ] Starting Contrast Agent runner pre-process
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/contrast_security.yml
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/settings/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/settings/contrast_security.yml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast/python/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast/python/contrast_security.yml
2024-06-05 15:15:50 [info ] Loading configuration file: /etc/contrast/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast/contrast_security.yml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast_security.yml
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/contrast_security.yml
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/settings/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /app/pygoat/settings/contrast_security.yml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast/python/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast/python/contrast_security.yml
2024-06-05 15:15:50 [info ] Loading configuration file: /etc/contrast/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast/contrast_security.yml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast_security.yaml
2024-06-05 15:15:50 [debug ] Configuration file not found: /etc/contrast_security.yml
2024-06-05 15:15:50 [debug ] registering automatic middleware patches
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.django
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.mod_wsgi
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.flask
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.bottle
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.pyramid.router
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.fastapi
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.aiohttp
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.falcon
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.falcon.asgi
2024-06-05 15:15:50 [debug ] registering middleware patches for contrast.patches.middleware.quart
2024-06-05 15:15:51 [debug ] Configuration file not found: /app/pygoat/contrast_security.yaml
2024-06-05 15:15:51 [debug ] Configuration file not found: /app/pygoat/contrast_security.yml
2024-06-05 15:15:51 [debug ] Configuration file not found: /app/pygoat/settings/contrast_security.yaml
2024-06-05 15:15:51 [debug ] Configuration file not found: /app/pygoat/settings/contrast_security.yml
2024-06-05 15:15:51 [debug ] Configuration file not found: /etc/contrast/python/contrast_security.yaml
2024-06-05 15:15:51 [debug ] Configuration file not found: /etc/contrast/python/contrast_security.yml
2024-06-05 15:15:51 [info ] Loading configuration file: /etc/contrast/contrast_security.yaml
2024-06-05 15:15:51 [debug ] Configuration file not found: /etc/contrast/contrast_security.yml
2024-06-05 15:15:51 [debug ] Configuration file not found: /etc/contrast_security.yaml
2024-06-05 15:15:51 [debug ] Configuration file not found: /etc/contrast_security.yml
2024-06-05 15:15:51 [debug ] registering automatic middleware patches
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.django
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.mod_wsgi
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.flask
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.bottle
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.pyramid.router
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.fastapi
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.aiohttp
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.falcon
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.falcon.asgi
2024-06-05 15:15:51 [debug ] registering middleware patches for contrast.patches.middleware.quart
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
June 05, 2024 - 15:15:51
Django version 4.1.7, using settings 'pygoat.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
{"id": 281473031691568, "version": "8.2.0", "time": "2024-06-05T15:15:51.455873Z", "level": 30, "msg": "Initializing Contrast Agent contrast.agent.agent_state", "filename": "agent_state.py", "func_name": "initialize", "lineno": 354, "thread": 281473169961440, "pid": 7, "request_id": null, "hostname": "1faaa3b2f3e3", "name": "Contrast Agent", "v": 0}
{"time": "2024-06-05T15:15:51.514629Z", "level": 30, "msg": "Loading configuration file: /etc/contrast/contrast_security.yaml", "filename": "configuration_utils.py", "func_name": "_load_config", "lineno": 96, "thread": 281473169961440, "pid": 7, "request_id": null, "hostname": "1faaa3b2f3e3", "name": "Contrast Agent", "v": 0}
{"time": "2024-06-05T15:15:51.515514Z", "level": 30, "msg": "Contrast Agent finished loading settings.", "filename": "settings.py", "func_name": "init", "lineno": 118, "thread": 281473169961440, "pid": 7, "request_id": null, "hostname": "1faaa3b2f3e3", "name": "Contrast Agent", "v": 0}
Contrast Agent Logger updated level to ERROR
The Contrast Python Agent collects usage data in order to help us improve compatibility and security coverage. The data is anonymous and does not contain application data. It is collected by Contrast and is never shared. You can opt-out of telemetry by setting the CONTRAST_AGENT_TELEMETRY_OPTOUT environment variable to '1' or 'true'. Read more about Contrast Python Agent telemetry: https://docs.contrastsecurity.com/en/python-telemetry.html
Source code example: PyGoat
Use this GitHub repository to learn how first. It contains a lab that walks you through different ways to instrument Python applications via Docker for security monitoring with Contrast.
https://github.com/Contrast-Security-OSS/PyGoat
Known Issues