> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/install-an-engine/docker.md).

# Docker

Docker is a software framework for building, running, and managing containers.

{% hint style="info" %}

### Note

This section is relevant when installing an engine.
{% endhint %}

Cortex XSOAR maintains a repository of Docker images, available in the Docker hub under the [Cortex](https://hub.docker.com/u/demisto/) organization.

Each Python/PowerShell script or integration has a specific Docker image listed in the YAML file. When the script or integration runs, if the specified Docker image is not available locally, it is downloaded from the Docker hub or the Cortex Container Registry. The script or integration then runs inside the Docker container. For more information on Docker, see the [Docker documentation](https://docs.docker.com/) and [Using Docker](https://xsoar.pan.dev/docs/integrations/docker).

{% hint style="info" %}

### Note

Docker images can be [downloaded](https://xsoar.pan.dev/docs/reference/articles/download-packs-offline) together with their relevant content packs, for offline installation.
{% endhint %}

### **Install Docker**

Docker is required for engines to run Python/Powershell scripts and integrations in a controlled environment.

If you use the Shell installer to install an engine, Docker is automatically installed. If using DEB and RPM installations, you need to install Docker or Podman before installing an engine. The engine uses Docker to run Python scripts, PowerShell scripts, and integrations in a controlled environment. By packaging libraries and dependencies together, the environment remains the same and scripts and integrations are not affected by different server configurations.

Cortex XSOAR supports the latest Docker Engine release from Docker and the following corresponding supported Linux distributions:

* 5.3.15 and later
* 5.4.2 and later
* 5.5 and later

These Linux distributions include their own Docker Engine package. In addition, older versions of Docker Engine released within the last 12 months are supported unless there is a known compatibility issue with a specific Docker Engine version. In case of a compatibility issue, Cortex XSOAR will publish an advisory notifying customers to upgrade their Docker Engine version.

You can use a version that is not supported. However, when encountering an issue that requires Customer Support involvement, you may be asked to upgrade to a supported version before assistance can be provided.

### **Docker installation by operating system**

If you need to install Docker before installing an engine, use the following procedures:

* [Red Hat](#install-docker-distribution-for-red-hat-on-an-engine-server)
* [Ubuntu](https://docs.docker.com/engine/install/ubuntu/)
* [Amazon Linux](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/docker-basics.html#install_docker)
* [Oracle Linux](https://docs.oracle.com/en/operating-systems/oracle-linux/docker/)

{% hint style="info" %}

### Note

For Red Hat's Docker distribution, you need Mirantis Container Runtime (formerly Docker Engine - Enterprise) to run specific Docker-dependent integrations and scripts. For more information, see [Install Docker distribution for Red Hat on an engine server](#UUID-13138a2d-309b-2815-fae1-0a5a93c610d5).

To use the Mirantis Container Runtime (formerly Docker Engine - Enterprise) follow the [deployment guide](https://docs.mirantis.com/welcome/mcr) for your operating system distribution.
{% endhint %}

### **Verify Docker user and permissions**

#### **Verify Docker user**

If you installed an engine before installing Docker, verify the demisto operating system user is part of the docker operating system group.

1. Run **`id demisto`** verify. For example:

   ```programlisting
   id demisto
   uid=997(demisto) gid=997(demisto) groups=997(demisto),998(docker)
   ```

   If needed, add the demisto user to the operating system group:

   ```programlisting
   sudo groupadd docker
   sudo usermod -aG docker demisto
   ```

   Remove these keys from the engine configuration file.

   ```programlisting
   python.executable
   python.executable.no.docker
   ```

#### **Verify user permissions**

To verify that the operating system user (demisto) has necessary permissions and can run Docker containers, run the following command from the OS command line.

**`sudo -u demisto docker run --rm -it demisto/python:1.3-alpine python --version`**

If everything is configured properly you will receive the following output. `Python 2.7.14`.

### **Install Docker distribution for Red Hat on an engine server**

Red Hat maintains its own package of Docker, which is the version used in OpenShift Container Platform environments, and is available in the RHEL Extras repository.

{% hint style="info" %}

### Note

If running RHEL v8 or higher, the engine installs [Podman](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/install-an-engine/podman.md) packages and configures the operating system to enable Podman in rootless mode.
{% endhint %}

For more information about the different packages available to install on Red Hat, see the [Red Hat Knowledge Base Article](https://access.redhat.com/solutions/3092401) (requires a Red Hat subscription to access).

1. Install [Red Hat’s Docker package](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_atomic_host/7/html-single/getting_started_with_containers/index#using_the_docker_command_and_service).
2. Run the following commands.

   **`systemctl enable docker.service`**

   **`systemctl restart docker.service`**
3. Change ownership of the Docker daemon socket so members of the **`dockerroot`** user group have access.
   1. Edit or create the file `/etc/docker/daemon.json`.
   2. Enable OS group **`dockerroot`** access to Docker by adding the following entry to the `/etc/docker/daemon.json: "group": "dockerroot"`file. For example:

      **`{ "group": "dockerroot" }`**
   3. Restart the Docker service by running the following command.

      **`systemctl restart docker.service`**
   4. [Install an engine](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/install-an-engine.md).
   5. After the engine is installed, run the following command to add the **`demisto`** os user to the **`dockerroot`** os group (Red Hat uses dockerroot group instead of docker).

      **`usermod -aG dockerroot demisto`**
   6. Restart the engine.
4. Set the required SELinux permissions.

   The Cortex XSOAR engine uses the `/var/lib/demisto/temp` directory (with subdirs) to copy files and receive files from running Docker containers. By default, when SELinux is in **enforcing** mode directories under **`/var/lib/`** it cannot be accessed by Docker containers.

   1. To allow containers access to the `/var/lib/demisto/temp` directory, you need to set the correct SELinux policy type, by typing the following command.

      **`chcon -Rt svirt_sandbox_file_t /var/lib/demisto/temp`**
   2. ( Optional) Verify that the directory has the **`container_file_t`** SELinux type attached by running the following command.

      **`ls -d -Z /var/lib/demisto/temp`**
   3. Configure label confinement to allow Python and PowerShell containers to access other script folders.

      In the d1.conf file, set the following parameters:

      |                           | Key                        | Value                                   |
      | ------------------------- | -------------------------- | --------------------------------------- |
      | For Python containers     | python.pass.extra.keys     | --security-opt=label=level:s0:c100,c200 |
      | For PowerShell containers | powershell.pass.extra.keys | --security-opt=label=level:s0:c100,c200 |
   4. Open any incident and in the incident War Room CLI, run the **`/reset_containers`** command.

### **Docker image security**

The project that contains the source Dockerfiles used to build the images and the accompanying files is fully open source and [available for review](https://github.com/demisto/dockerfiles). Cortex XSOAR uses the secure Docker Hub registry for its [Docker images](https://hub.docker.com/u/demisto). However, in an Engine environment, you can also use the [PANW registry](#UUID-98076b57-6ab4-4cc9-964b-ddfcddd1ff3a) . You can view the Docker trust information for each image at the [image info branch](https://github.com/demisto/dockerfiles-info/blob/master/README.md).

![docker-trust.png](/files/HzYgI4OPhuTyzunVMenb)

We automatically update our open source Docker images and their accompanying dependencies (OS and Python). Examples of automatic updates can be viewed on [GitHub](https://github.com/demisto/dockerfiles/pull/700).

We maintain Docker image information which includes information on Python packages, OS packages and image metadata for all our Docker images. [Data image information](https://github.com/demisto/dockerfiles-info/blob/master/README.md) is updated nightly.

All of our images are continuously scanned using Prisma Cloud for known and newly published vulnerabilities, in two scenarios:

* Every new image, and every new version of an image, are scanned before publishing to our public registries, as part of our CI/CD process.
* All existing images are continuously scanned to check whether new vulnerabilities were published and now exist in those images.

We evaluate all critical/high findings and actively work to prevent and mitigate security vulnerabilities.

Cortex XSOAR ensures container images are fully patched and do not contain unnecessary packages. Patches and dependencies are applied automatically via our open source docker files build project.

### **Response Prioritization**

We remediate any critical and high level vulnerabilities, irrespective of who found them. Issues may be discovered by external researchers, found during internal testing, encountered by customers or reported by other organizations and vendors.

Any vulnerability with a possible exploitation against our images would be responded to with utmost urgency. If we conclude that there is a risk for our customers we will issue an advisory with recommended actions and mitigations. Advisories are published at: <https://security.paloaltonetworks.com/>.

In each version release (every 3 months,) we publish a new version of our content, that will use the latest and secure versions of our images.

### **Troubleshooting**

* Purge old and unused images periodically.
* If you scanned the Docker images locally, and found some critical CVE’s - Make sure you use the latest version of the pack, as it should have the latest version of the image. In addition, purge the old and unused image with vulnerabilities.

### **Use the Cortex XSOAR Container Registry**

By default, Cortex XSOAR uses Docker Hub's public container registry. As an alternative to using Docker Hub, you can use the Cortex XSOAR private container registry (XSOAR Registry), which contains all Docker images that Cortex XSOAR uses in integrations and automations. When you use the XSOAR Container Registry, you can avoid limitations that Docker imposes on Docker Hub, for example rate limits. The registry is available at: **`xsoar-registry.pan.dev`**.

The XSOAR Registry requires authentication using the following credentials:

* Username: Use the license Customer Name, by going to Settings → About → **License**.
* Password: Use the License ID. To obtain the License ID, go to the License file and copy the ID from the **`id`** property, or run the **`!GetLicenseID`** command, included in the **Common Scripts** content pack.

  The License ID starts and ends with the CUID string.

To pull Docker images from the XSOAR Registry, verify the following base URLs are allowed in your firewall/proxy:

* **`https://xsoar-registry.pan.dev`**
* **`https://gcr.io`**

When using a custom Docker registry, including the Cortex XSOAR Container Registry, you must include **`localhost`** when you create a custom Docker image. Examples:

* **`localhost.local/directory/container_name`**
* **`localhost/directory/container_name`**

1. Authenticate to the XSOAR Registry.

   * For Docker: **` sudo -u demisto docker login -u`` `` `*****`<license customer name>`*****`-p`*****`<license id>`*****`xsoar-registry.pan.dev`**
   * For Podman (Red Hat 8.x): **`sudo su -s /bin/bash - demisto -c 'podman login -u "<license customer name>" -p "<license id>" xsoar-registry.pan.dev'`**

   If you see an error such as **`Error saving credentials: mkdir /home/demisto: permission denied`**, the demisto user is either missing the home directory or the permissions on the directory are not valid.

   1. To verify the home directory assigned to the demisto user, run **`echo ~demisto`** to display the home directory, such as: **`/home/demisto`**.
   2. To ensure the directory exists and has the correct permissions, run the following commands, using the directory from **`echo ~demisto`**:

      **` sudo mkdir -p`` `` `*****`/home/demisto`***

      **` sudo chown -R demisto:demisto`` `` `*****`/home/demisto`***
2. Test that the XSOAR Registry is properly authenticated.
   * For Docker: **`sudo -u demisto docker pull xsoar-registry.pan.dev/demisto/python3:3.10.4.27798`**
   * For Podman (Red Hat 8.x): **`sudo su -s /bin/bash - demisto -c 'podman pull xsoar-registry.pan.dev/demisto/python3:3.10.4.27798'`**
3. Apply the following configuration to the engine machine by adding to the JSON file:

   ```programlisting
   {
       “python.docker.registry”: “xsoar-registry.pan.dev"
       }
   ```
4. Test a Docker based automation or integration.

If you need to use external Docker images (images not available in the XSOAR Registry and not part of the demisto org) in custom content, specify the full image name with the registry prefix in the automation or integration configuration. For example:

* docker.io/frolvlad/alpine-python2:latest
* registry.access.redhat.com/ubi8/python-38:latest
* myregistryhost:5000/myorg/myimage:version1.0

### **Docker FAQs**

* **Does Cortex XSOAR use COPY or ADD for building images?**

  Cortex XSOAR uses COPY for building images. The COPY instruction copies files from the local host machine to the container file system. Cortex XSOAR does not use the ADD instruction, which could potentially retrieve files from remote URLs and perform operations such as unpacking, introducing potential security vulnerabilities.
* **Should the** **`--restart flag`** **be used?**

  The --restart flag should not be used. Cortex XSOAR manages the lifecycle of Docker images and restarts images as needed.
* **Can we restrict containers from acquiring additional privileges by setting the no-new-privileges option?**

  Cortex XSOAR does not support the no-new-privileges option. Some integrations and scripts may need to change privileges when running as a non-root user (such as Ping).
* **Can we apply a daemon-wide custom seccomp profile?**

  The [default seccomp profile](https://docs.docker.com/engine/security/seccomp/) from Docker is strongly recommended. The default seccomp profile provides protection as well as wide application compatibility. While you can apply a custom seccomp profile, Cortex XSOAR cannot guarantee that it won't block system calls used by an integration or script. If you apply a custom seccomp profile, you need to verify and test the profile with any integrations or scripts you plan to use.
* **Can we use TLS authentication for docker daemon configuration?**

  TLS authentication is not used, because Cortex XSOAR does not use Docker remote connections. All communication is done via the local Docker IPC socket.
* **How do we set the logging level to** **`info`**?

  Set the log level in the [Docker daemon configuration file](https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file).
* **Can we restrict Linux kernel capabilities within containers?**

  The default Docker settings (recommended) include 14 kernel capabilities and exclude 23 kernel capabilities. Refer to Docker’s [full list of runtime privileges and Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).

  You can further exclude capabilities via advanced configuration, but will first need to verify that you are not using a script that requires the capability. For example, Ping requires **`NET_RAW`** capability.
* **Is the Docker health check option implemented at runtime?**

  The Cortex XSOAR tenant monitors the health of the containers and restarts/terminates containers as needed. The Docker health check option is not needed.
* **Can we enable live restore?**

  Live restore is not used. Cortex XSOAR uses ephemeral Docker containers. Every running container is stateless by design.
* **Can we restrict network traffic between containers?**

  Cortex XSOAR does not disable inter-container communication by default, as there are use cases where this might be needed. For example, a script communicating with a long running integration which listens on a port, may require inter-container communication. If inter-container communication is not required, it can be disabled by modifying the [Docker daemon configuration.](https://docs.docker.com/engine/reference/commandline/dockerd/)
* **Can we enable user namespace remapping?**

  Cortex XSOAR does not support user namespace remapping.
* **How do we configure auditing for Docker files and directories?**

  Auditing is an operating system configuration, and can be enabled in the operating system settings. Cortex XSOAR does not change the audit settings of the operating system.
* **Does Cortex XSOAR map privileged ports?**

  Cortex XSOAR does not map privileged ports (TCP/IP port numbers below 1024).
* **Does Cortex XSOAR allow privileged execution?**

  Cortex XSOAR does not allow privileged execution of Docker commands.
* **Does Cortex XSOAR run SSH within containers?**

  Cortex XSOAR does not run SSH within containers.
* **Does Cortex XSOAR change the ownership of the socket?**

  Cortex XSOAR does not change the ownership of the socket.
* **Can we disable the userland proxy?**

  If the kernel supports hairpin NAT, you can disable docker userland proxy settings by modifying the [Docker daemon configuration](https://docs.docker.com/engine/reference/commandline/dockerd/).
* **Does Cortex XSOAR support the AppArmor profile?**

  Cortex XSOAR supports the default AppArmor profile (only relevant for Ubuntu with AppArmor enabled).
* **Does Cortex XSOAR support the SELinux profile?**

  Cortex XSOAR supports the default SELinux profile (only relevant for RedHat with SELinux enabled).
* **How does Cortex XSOAR handle secrets management?**

  For Docker swarm services, a secret is a blob of data, such as password, SSH private keys, SSL certificates, or other piece of data that should not be transmitted over a network or stored unencrypted in a Docker file or in your application’s source code. Cortex XSOAR manages integration credentials internally. It also supports using an [external credentials service](https://xsoar.pan.dev/docs/reference/articles/managing-credentials) such as CyberArk.

### **Troubleshoot Docker issues**

The following provides troubleshooting solutions for Docker networking and performance issues.

#### &#x20;**Troubleshoot Docker networking issues**

In Cortex XSOAR, integrations and scripts run either on the tenant, or on an engine.

If you have Docker networking issues when using an engine, you need to modify the d1.conf file.

1. On the machine where the Engine is installed, open the **`d1.conf`** file.
2. Add the following to the **`d1.conf`** file:

   ```programlisting
   {
       "LogLevel": "info",
       "LogFile": "/var/log/demisto/d1.log",
       "EngineURLs": [
       "wss://1234.demisto.live/d1ws"
       ],
                       "BindAddress": ":443",
       "EngineID": "XYZ",
       "ServerPublic": "ABC"
       "ArtifactsFolder": "",
       "TempFolder": "",
       "python.pass.extra.keys": "--network=host"
       }
   ```
3. Save the file.
4. Restart the engine using **`systemctl restart d1`** or **`service d1 restart`**.

#### **Troubleshoot Docker performance issues**

This information is intended to help resolve the following Docker performance issues.

* Containers are getting stuck.
* The Docker process consumes a lot of resources.
* Time synchronization issues between the container and the operating system.

**Cause**

The installed Docker package and its dependencies are not up to date.

**Workaround**

1. Update the package manager cache.

   | Linux Distribution | Command              |
   | ------------------ | -------------------- |
   | Debian             | **`apt-get update`** |
2. (Optional) Check for a newer version of the Docker package.

   | Linux Distribution | Command                       |
   | ------------------ | ----------------------------- |
   | Debian             | **`apt-cache policy docker`** |
3. Update the Docker package.

   | Linux Distribution | Command                     |
   | ------------------ | --------------------------- |
   | Debian             | **`apt-get update docker`** |

### **Configure Docker pull rate limit**

Docker enforces a [pull rate limit](https://www.docker.com/blog/scaling-docker-to-serve-millions-more-developers-network-egress/) on public images. The limit is based on an IP address or as a logged-in Docker hub user. The default limit (100 pulls per 6 hours) is usually high enough for Cortex XSOAR's use of Docker images, but the rate limit may be reached if using a single IP address for a large organization (behind a NAT). If the rate limit is reached, the following error message is issued:

`Error response from daemon: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit.`

To increase the limit:

1. Sign up a free user [in the Docker hub](https://hub.docker.com/signup/).

   The pull limit is higher for a registered user (200 pulls per 6 hours).
2. Authenticate the user on the engine machine by running the following command.

   **`sudo -u demisto docker login`**
3. (Optional) Instead of manually logging in to Docker to pull images, you can edit the [Docker config file](https://docs.docker.com/engine/reference/commandline/login/) to use credentials from the file or from a credential store.

### **Change the Docker installation folder**

The **`/var/lib/docker/`** folder is the default Docker folder for Ubuntu, Fedora, and Deblan in a standard engine installation.

To change the Docker folder:

1. Stop the Docker daemon.

   **`sudo service docker stop`**
2. Create a file called **`daemon.json`** under the **`/etc/docker`** directory with the following content:

   ```programlisting
   {
           "data-root": "<path to your Docker folder>"
     }
   ```
3. Copy the current data directory to the new one.

   **`sudo rsync -aP /var/lib/docker/ <path to your Docker folder>`**
4. Rename the old docker directory.

   **`sudo mv /var/lib/docker /var/lib/docker.bkp`**
5. After confirming that the change was successful, you can remove the backup file.

   **`sudo rm -rf /var/lib/docker.bkp`**
6. Start the Docker daemon.

   **`sudo service docker start`**

### **Configure Docker integrations to trust custom certificates**

Python, Javascript, and native integrations running in Docker use an engine's built-in set of CA-signed certificates to validate TLS communication. If you need to change the certificate bundle of the operating system you are working on, for Javascript and native integrations you need to add custom trusted certificates to the engine built-in set, and for Python Docker integrations you need to create a certificate file that includes the custom certificates and add it to the engine. This is relevant for example if you work with a proxy that performs SSL traffic inspection or use a service that has a self-signed certificate.

#### **Configure Javascript and Native integrations to trust custom certificates**

1. Add the certificate to the machine’s trusted root CA bundle. The location of the CA bundle depends on the operating system version and the operating configuration.

   Examples of bundle paths:

   * "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
   * "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
   * "/etc/ssl/ca-bundle.pem", // OpenSUSE
   * "/etc/pki/tls/cacert.pem", // OpenELEC
   * "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", //RHEL 7
   * "/etc/ssl/cert.pem", // Alpine Linux

   Examples of certificate bundle directories:

   * "/etc/ssl/certs", // SLES10/SLES11, <https://golang.org/issue/12139>
   * "/etc/pki/tls/certs", // Fedora/RHEL
2. Restart the engine.

#### **Configure Python Docker integrations to trust custom certificates**

This procedure assumes that the Cortex XSOAR **`lib dir`** is configured to the default location `/var/lib/demisto`.

{% hint style="info" %}

### Note

* Only PEM format for certificates is supported.
* `/var/lib/demisto` requires root access. This is relevant for Docker and Podman.
  {% endhint %}

1. Configure the custom certificates for the engine.
   1. Create a certificate PEM file that includes all of the required custom certificates.
      * To examine the certificate chain used by a specific endpoint, run the following command on the engine machine (requires openssl client):

        **`openssl s_client -servername <host_name> -host <host_name> -port 443 -showcerts < /dev/null`**

        For example, **`openssl s_client -servername api.github.com -host api.github.com -port 443 -showcerts < /dev/null`**

        This prints certificate information including the PEM representation of the certificates. After examining the output, if you see **`Verification error: unable to get issuer certificate`**, one or more certificates in the certificate chain is not available and you need to obtain these certificates from your IT administrator.
      * To save the certificates to a **`certs.pem`** file run the following command:

        **`openssl s_client -servername api.github.com -host api.github.com -port 443 -showcerts < /dev/null 2>/dev/null | sed -n '/^-----BEGIN CERT/,/^-----END CERT/p' > certs.pem`**
      * To verify that the **`certs.pem`** has all needed certificates as part of the certificate chain, run **`openssl verify -CAfile certs.pem site.pem`**, where **`site.pem`** contains the certificate of a specific site you want to trust. To get the cert of a site, run **`openssl s_client -servername <site_host> -host <site_host> -port 443`** and copy the base content including `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----`.
      * After saving the **`certs.pem`** file, add its content to **`/var/lib/demisto/python-ssl-certs.pem`**, by running the following command:

        **`cat certs.pem >> /var/lib/demisto/python-ssl-certs.pem`**
   2. (RedHat only) Set the required SELinux permissions.
      * By default, when SELinux is in enforcing mode, directories under **`/var/lib/`** cannot be accessed by Docker containers. To allow container access to the **`/var/lib/demisto/python-ssl-certs.pem`** file, you need to set the correct SELinux policy type, by typing the following command:

        **`chcon -t svirt_sandbox_file_t /var/lib/demisto/python-ssl-certs.pem`**
      * (Optional) Verify that the file has the **`container_file_t SELinux`** type attached by running the following command:

        **`ls -d -Z /var/lib/demisto/python-ssl-certs.pem`**
   3. (Optional) If you require the standard set of certificates trusted by browsers, you can append the CA certificates provided by your operating system. For example, on Ubuntu, these certificates are located at the following path: **`/etc/ssl/certs/ca-certificates.crt`**. Alternatively, you can download the PEM certificates file provided by the Certifi Project and add your custom certificates to the file that contains the standard set of certificates. For more details, see the [cacert.pem file](https://raw.githubusercontent.com/certifi/python-certifi/master/certifi/cacert.pem).

      This example adds the `proxy-ca.pem` file (custom certificate) to the `cacert.pem` file (standard certificates): **`cat proxy-ca.pem >> cacert.pem`**
   4. Copy the certificates PEM file to the following path.

      `/var/lib/demisto/python-ssl-certs.pem`

      (Multi-tenant) In a multi-tenant deployment, the certificate is copied to the following path on the host machine: **`/var/lib/demisto/tenants/acc_`*****`TENANT`*****`/python-ssl-certs.pem`**
2. Add the certificate file to your engines.

   1. Configure each engine to use the `/var/lib/demisto/python-ssl-certs.pem` file.
      1. Verify you have the following directory on the engine host.

         `/var/lib/demisto`
      2. Set the **demisto** user as the directory owner with **0700** permissions.
      3. Copy the `python-ssl-certs.pem` file to the `/var/lib/demisto directory`.
      4. Add the following configuration to either the engine configuration file (in the UI) or to the `d1.conf` file.

         **`"python.docker.use_custom_certs": true`**
   2. Restart the engine.

   After saving the **`python.docker.use_custom_certs`** configuration on your engine, Docker images that are launched by the engine will contain the certificates file mounted in the following path:

   `/etc/custom-python-ssl/certs.pem`

   Additionally, the following environment variables will be set with the value of the certificates file path, which enables standard Python HTTP libraries to automatically trust the certificates (without code modifications):

   * `REQUESTS_CA_BUNDLE`
   * `SSL_CERT_FILE`

     The Python SSL library checks the `SSL_CERT_FILE` environment variable only when using OpenSSL. If you use a Docker image that uses `LibreSSL`, the `SSL_CERT_FILE` environment variable will be ignored. For more details, see [LibreSSL support](https://docs.python.org/2.7/library/ssl.html#libressl-support).

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><h3>Note</h3><p>If you are developing your own integration (BYOI) and using non-standard HTTP libraries, you might need to include specific code that will trust the passed certificates file when the environment variable SSL_CERT_FILE is set. In this case, always use the value in the environment variable as the path for the certificates file, and do not hard code the mounted path specified above. For example:</p><pre class="language-screen"><code class="lang-screen">certs_file = os.environ.get('SSL_CERT_FILE')
   if certs_file:
               # perform custom logic to trust certificates...
   </code></pre></div>
3. Check the integration runs correctly on your engine.

   For more information about troubleshooting, see [TLS/SSL troubleshooting](https://xsoar.pan.dev/docs/reference/articles/troubleshooting-guide#tlsssl-troubleshooting).

### **Docker hardening guide**

The following describes the engine settings we recommend for securely running Docker containers on Ubuntu, using iptables to restrict IP access.

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"}`

{% hint style="info" %}

### 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.
{% endhint %}

You can *Check Docker Hardening Configurations* to verify that the Docker container has been hardened according to the settings we recommend.

{% hint style="info" %}

### Note

The settings below can also be applied to [Podman](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/install-an-engine/podman.md), with the exception of limiting available memory, limiting available CPU, and limiting PIDS.
{% endhint %}

<details>

<summary>Docker network hardening</summary>

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's **`daemon.json`** config file, use the configured range. Alternatively, you can limit specific interfaces by using the interface name, such as **`docker0`**, as a source.

  1. 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`**
  2. (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 documentation

  There 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`**

  1. 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`**
  2. 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](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/configure-engines.md).
  3. Add the following key.

     **`"python.pass.extra.keys.demisto/boto3py3": "--network=aws-metadata"`**
  4. Save the changes.
  5. Restart the demisto service on the engine machine.

     **`sudo systemctl start d1`**

     (Ubuntu) **`sudo service d1 restart`**
  6. 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.

  1. 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`**
  2. Block network access to the host machine for the new Docker network:

     **`iptables -I INPUT -i docker-external -d <host private ip> -j DROP`**
  3. Block network access to cloud provider instance metadata:

     **`sudo iptables -I DOCKER-USER -i docker-external -d 169.254.169.254/32 -j DROP`**
  4. 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`**
  5. 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](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/configure-engines.md).
  6. Add the following key to run integrations that use the **`demisto/chromium`** Docker image with the Docker network **`external`**.

     **`"python.pass.extra.keys.demisto/chromium": "--network=external"`**
  7. Save the changes.
  8. Restart the demisto service on the engine machine.

     **`sudo systemctl start d1`**

     (Ubuntu) **`sudo service d1 restart`**
  9. 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:

  * [Ubuntu](https://help.ubuntu.com/community/IptablesHowTo)
  * [Red Hat and related operating system flavors](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-setting_and_controlling_ip_sets_using_iptables)

</details>

<details>

<summary>Configure Docker images</summary>

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.

1. 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](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/configure-engines.md).
2. 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"`**
3. Save the changes.
4. Restart the demisto service on the engine machine.

   **`sudo systemctl start d1`**

   (Ubuntu) **`sudo service d1 restart`**

</details>

<details>

<summary>Run Docker with non-root internal users</summary>

For additional security isolation, we recommend to run Docker containers as non-root internal users. This follows the principle of least privilege.

1. 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](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/configure-engines.md).
2. Add the following key:

   **`"docker.run.internal.asuser": true`**
3. 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:

   ```programlisting
   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 find **`demisto/python-ubuntu:2.7.16.373`**.
4. Save the changes.
5. Restart the demisto service on the engine machine.

   **`sudo systemctl start d1`**

   (Ubuntu) **`sudo service d1 restart`**

</details>

<details>

<summary>Configure the memory limit support without swap limit capabilities</summary>

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.

How to check if your system supports swap limit capabilities

1. On the engine machine, run the following command:

   **`sudo docker run --rm -it --memory=1g demisto/python:1.3-alpine true`**
2. If **`swap limit capabilities`** is enabled, configure the memory limitation . (To test the memory, see **Step 5. Test the memory limit** in Configure the memory limitation.)
3. 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](https://docs.docker.com/config/containers/resource_constraints/).
   * See **How to configure the memory limit support without swap limit capabilities** below.

   If you see the **`WARNING: No swap limit support`** you can configure memory support without swap limit capabilities.

How to configure the memory limit support without swap limit capabilities

1. 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](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/configure-engines.md).
2. 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.
3. Save the changes.
4. Restart the demisto service on the engine machine.

   **`sudo systemctl start d1`**

   (Ubuntu) **`sudo service d1 restart`**

</details>

<details>

<summary>Configure the memory limitation</summary>

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.

1. 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](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/configure-engines.md).
2. Add the following keys.

   **`"limit.docker.memory": true, "docker.memory.limit": "1g"`**

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><h3>Note</h3><p>If you do not want to apply Docker memory limitations you should explicitly set the advanced parameter: <strong><code>limit.docker.memory</code></strong> to <strong><code>false</code></strong>.</p></div>
3. Save the changes.
4. Restart the demisto service on the engine machine.

   **`sudo systemctl start d1`**

   (Ubuntu) **`sudo service d1 restart`**
5. Test the memory limit.
   1. Go to **Scripts** and click **New Script**.
   2. In the **Script Name** file, type **`TestMemory`**.
   3. Add the following script:

      ```programlisting
      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))
      ```
   4. 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.
   5. Save the script.
   6. To test the memory limit, type **`!TestMemory`**. The command returns an error when it fails to allocate 1 GB of memory.

</details>

<details>

<summary>Configure the CPU, PIDs, and open file descriptors limit</summary>

Set the advanced parameters to configure the CPU limit, PIDs limit and the open file descriptor limit.

1. 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](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/configure-engines.md).
2. 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"`**                                                                                                              |
3. Save the changes.
4. Restart the demisto service on the engine machine.

   **`sudo systemctl start d1`**

   (Ubuntu) **`sudo service d1 restart`**

</details>

<details>

<summary>Check Docker hardening configurations</summary>

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.

1. Update the **`DockerHardeningCheck`** script to run on the engine.

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><h3>Note</h3><p>By default, the <strong><code>DockerHardeningCheck</code></strong> script runs on the Cortex XSOAR tenant.</p></div>

   1. Go to **Incident Response** → **Automation** → **Scripts** → **DockerHardeningCheck** → **Settings**.
   2. In the **Run on** field select **Single engine** and from the list, select the engine you want to run the script.
   3. Save the script.
2. Verify the Docker container has been hardened according to recommended settings, in the CLI, run the !DockerHardeningCheck command.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cortex-docs.paloaltonetworks.com/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/engines/install-an-engine/docker.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
