Use the Docker Hardening Guide to configure the Cortex XSOAR settings when running Docker containers.
The following describes the engine settings we recommend for securely running Docker containers.
When editing the configuration file, you can limit container resources, open file descriptors, limit available CPU, and more. For example, add the following keys to the configuration file:
{"docker.run.internal.asuser": true,"limit.docker.cpu": true,"limit.docker.memory": true,"python.pass.extra.keys": "--pids-limit=256##--ulimit=nofile=1024:8192"}
Tip
We recommend reviewing Docker network hardening below, before changing any parameters in the configuration file.
To securely run Docker containers, we recommend to use the latest Docker version.
You can Check Docker Hardening Configurations to verify that the Docker container has been hardened according to the settings we recommend.
Note
The settings below can also be applied to Podman, with the exception of limiting available memory, limiting available CPU, and limiting PIDS.
Docker creates its own networking stack that enables containers to communicate with other networking endpoints. You can use iptables rules to restrict which networking sources the containers communicate with. By default, Docker uses a networking configuration that allows unrestricted communication for containers, so that containers can communicate with all IP addresses.
Block network access to the host machine
Integrations and scripts running within containers do not usually require access to the host network. For added security, you can block network access from containers to services running on the engine machine.
For example, to limit all source IPs from containers that use the IP ranges 172.16.0.0/12, run
sudo iptables -I INPUT -s 172.16.0.0/12 -d 10.18.18.246 -j DROP
. This also ensures that new Docker networks which use addresses in the IP address range of 172.16.0.0/12 are blocked from access to the host private IP. The default IP range used by Docker is 172.16.0.0/12. If you configured a different range in Docker'sdaemon.json
config file, use the configured range. Alternatively, you can limit specific interfaces by using the interface name, such asdocker0
, as a source.Add the following iptables rule for each private IP on the tenant machine:
sudo iptables -I INPUT -s <
IP address range
> -d <host private ip address
> -j DROP(Optional) To view a list of all private IP addresses on the host machine, run
sudo ifconfig -a
Assign a Docker network for a Docker image
If your engine is installed on a cloud provider such as AWS or GCP, it is a best practice to block containers from accessing the cloud provider’s instance metadata service. The metadata service is accessed via IP address
169.254.169.254
. For more information about the metadata service and the data exposed, see the AWS and GCP documentationThere are cases where you might need to provide access to the metadata service. For example, access is required when using an AWS integration that authenticates via the available role from the instance metadata service. You can create a separate Docker network, without the blocked iptable rule, to be used by the AWS integration’s Docker container. For most AWS integrations the relevant Docker image is:
demisto/boto3py3
Create a new Docker network by running the following command:
sudo docker network create -d bridge -o com.docker.network.bridge.name=docker-metadata aws-metadata
Edit the engine configuration file either by editing the
d1.conf
file, or If you installed via Shell, you can edit the configuration in the UI as well as editing the file directly. For details, see Configure engines.Add the following key.
"python.pass.extra.keys.demisto/boto3py3": "--network=aws-metadata"
Save the changes.
Restart the demisto service on the engine machine.
sudo systemctl start d1
(Ubuntu)
sudo service d1 restart
Verify the configuration of your new Docker network:
sudo docker network inspect aws-metadata
Block internal network access
In some cases, you might need to block specific integrations from accessing internal network resources and allow the integrations to access only external IP addresses. We recommend this setting for the Rasterize integration when used to Rasterize untrusted URLs or HTML content, such as those obtained via external emails. With internal network access blocked, a rendered page in the Rasterize integration cannot perform a SSRF or DNS rebind attack to access internal network resources.
Create a new Docker network by running the following command:
sudo docker network create -d bridge -o com.docker.network.bridge.name=docker-external external
Block network access to the host machine for the new Docker network:
iptables -I INPUT -i docker-external -d <host private ip> -j DROP
Block network access to cloud provider instance metadata:
sudo iptables -I DOCKER-USER -i docker-external -d 169.254.169.254/32 -j DROP
Block internal network access:
sudo iptables -I DOCKER-USER -i docker-external -d 10.0.0.0/8 -j DROP
sudo iptables -I DOCKER-USER -i docker-external -d 172.16.0.0/12 -j DROP
sudo iptables -I DOCKER-USER -i docker-external -d 192.168.0.0/16 -j DROP
Edit the engine configuration file either by editing the
d1.conf
file, or If you installed via Shell, you can edit the configuration in the UI as well as editing the file directly. For details, see Configure engines.Add the following key to run integrations that use the
demisto/chromium
Docker image with the Docker networkexternal
."python.pass.extra.keys.demisto/chromium": "--network=external"
Save the changes.
Restart the demisto service on the engine machine.
sudo systemctl start d1
(Ubuntu)
sudo service d1 restart
Verify the configuration of your new Docker network:
sudo docker network inspect external
Persist iptables rules
By default, iptables rules are not persistent after a reboot. To ensure your changes are persistent, save the iptables rules by following the recommended configuration for your Linux operating system:
You can apply more specific fine tuned settings to Docker images, according to the Docker image name or the Docker image name including the image tag. To apply settings to a Docker image name, add the advanced configuration key to the engine configuration file. If you apply Docker image specific settings, they will be used instead of the general python.pass.extra.keys
setting. This overrides the general memory and CPU settings, as needed.
Edit the engine configuration file either by editing the
d1.conf
file, or If you installed via Shell, you can edit the configuration in the UI as well as editing the file directly. For details, see Configure engines.Add the following key to apply settings to a Docker image name.
"python.pass.extra.keys.<image_name>"
For example,
"python.pass.extra.keys.demisto/dl"
.To apply settings to a Docker image name including the image tag, use
"python.pass.extra.keys.<image_name>": "<image_tag>"
.For example,
"python.pass.extra.keys.demisto/dl": "1.4"
.To set the Docker images
demisto/dl
(all tags) to use a higher max memory value of 2g and to remain with the recommended PIDs and ulimit, add the following to the configuration file:"python.pass.extra.keys.demisto/dl": "--memory=2g##--ulimit=no- file=1024:8192##--pids-limit=256"
Save the changes.
Restart the demisto service on the engine machine.
sudo systemctl start d1
(Ubuntu)
sudo service d1 restart
For additional security isolation, we recommend to run Docker containers as non-root internal users. This follows the principle of least privilege.
Edit the engine configuration file either by editing the
d1.conf
file, or If you installed via Shell, you can edit the configuration in the UI as well as editing the file directly. For details, see Configure engines.Add the following key:
"docker.run.internal.asuser": true
For containers that do not support non-root internal users, add the following key:
"docker.run.internal.asuser.ignore" : "A comma separated list of container names. The engine matches the container names according to the prefixes of the key values>"
For example,
"docker.run.internal.asuser.ignore"="demisto/python3:","demisto/python:"
The engine matches the key values for the following containers:
demisto/python:1.3-alpine demisto/python:2.7.16.373 demisto/python3:3.7.3.928 demisto/python3:3.7.4.977
The
:
character should be used to limit the match to the full name of the container. For example, using the:
character does not finddemisto/python-ubuntu:2.7.16.373
.Save the changes.
Restart the demisto service on the engine machine.
sudo systemctl start d1
(Ubuntu)
sudo service d1 restart
When a container exceeds the specified amount of memory, the container starts to swap. Not all Linux distributions have the swap limit support enabled by default.
Red Hat distributions usually have swap limit support enabled by default.
Ubuntu distributions usually have swap limit support disabled by default.
To protect the host from a container using too many system resources (either because of a software bug or a DoS attack), limit the resources available for each container. In the engine configuration file, some of these settings are set using the advanced parameter: python.pass.extra.keys
. This key receives as a parameter full docker run
options, separated with the ##
string.
On the engine machine, run the following command:
sudo docker run --rm -it --memory=1g demisto/python:1.3-alpine true
If
swap limit capabilities
is enabled, configure the memory limitation . (To test the memory, see step 5 of configure the memory limitation.)If you see the following message in the output (the message may vary between Docker versions):
WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
You have 2 options:
Configure
swap limit capabilities
by following the Docker documentation.See How to configure the memory limit support without swap limit capabilities.
If you see the
WARNING: No swap limit support
you can configure memory support without swap limit capabilities.
Edit the engine configuration file either by editing the
d1.conf
file, or If you installed via Shell, you can edit the configuration in the UI as well as editing the file directly. For details, see Configure engines.Add the following key to disable swap memory enforcement:
"python.pass.extra.keys": "--memory=1g##--memory-swap=-1"
If you have the
python.pass.extra.keys
already set up with a value, add the value after the##
separator.Save the changes.
Restart the demisto service on the engine machine.
sudo systemctl start d1
(Ubuntu)
sudo service d1 restart
We recommend to limit available memory for each container to 1 GB.
If swap limit capabilities
is enabled (see How to check if your system supports swap limit capabilities above), in Cortex XSOAR configure the memory limitation using the following advanced parameters.
Edit the engine configuration file either by editing the
d1.conf
file, or If you installed via Shell, you can edit the configuration in the UI as well as editing the file directly. For details, see Configure engines.Add the following keys.
"limit.docker.memory": true, "docker.memory.limit": "1g"
Note
If you do not want to apply Docker memory limitations you should explicitly set the advanced parameter:
limit.docker.memory
tofalse
.Save the changes.
Restart the demisto service on the engine machine.
sudo systemctl start d1
(Ubuntu)
sudo service d1 restart
Test the memory limit.
Go to Scripts and click New Script.
In the Script Name file, type
TestMemory
.Add the following script:
from multiprocessing import Process import os def big_string(size): sys.stdin = os.fdopen(0, "r") s = 'a' * 1024 while len(s) < size: s = s * 2 print('completed creating string of length: {}'.format(len(s))) size = 1 * 1024 * 1024 * 1024 p = Process(target=big_string, args=(size, )) p.start() p.join() if p.exitcode != 0: return_error("Return code from sub process indicates failure: {}".format(p.exitcode)) else: print("Success allocating memory of size: {}".format(size))
In the SCRIPT SETTINGS section, select the script to run on the Single engine and select the engine where you want to run the script.
Save the script.
To test the memory limit, type
!TestMemory
. The command returns an error when it fails to allocate 1 GB of memory.
Set the advanced parameters to configure the CPU limit, PIDs limit and the open file descriptor limit.
Edit the engine configuration file either by editing the
d1.conf
file, or If you installed via Shell, you can edit the configuration in the UI as well as editing the file directly. For details, see Configure engines.Add the following keys:
Parameter
Key
Available CPU limit
"limit.docker.cpu": true, "docker.cpu.limit": "<CPU Limit>"
We recommend to limit each container to 1 CPU. (For example,1.0
. Default is 1.0).PIDs limit
"python.pass.extra.keys": "--pids-limit=256"
Open file descriptors limit
"python.pass.extra.keys": "--ulimit=nofile=1024:8192"
Save the changes.
Restart the demisto service on the engine machine.
sudo systemctl start d1
(Ubuntu)
sudo service d1 restart
Check your Docker hardening configurations on an engine by running the !DockerHardeningCheck
command in the CLI. The results show the following:
Non-root User
Memory
File descriptors
CPUs
PIDs
Before running the command, ensure that your engine is up and running.
Update the
DockerHardeningCheck
script to run on the engine.Note
By default, the
DockerHardeningCheck
script runs on the Cortex XSOAR tenant.Go to Incident Response → Automation → Scripts → DockerHardeningCheck → Settings.
In the Run on field select Single engine and from the list, select the engine you want to run the script.
Save the script.
Verify the Docker container has been hardened according to recommended settings, in the CLI, run the !DockerHardeningCheck command.