Skip to main content
Skip table of contents

‎Install Agent on Linux

LAST UPDATED: FEB 14, 2025

Configuring and Running D3 Agent and D3 Executor

On the Proxy Agent, we will need to run both the d3executor and the d3agent containers.

  1. Create and edit a docker-compose.yml file and include the following content:

    YAML
    version:
    services:
      d3agent:
        image: "d3soar.azurecr.io/d3prod/d3agent:<D3 vSOC version>"
        restart: always
        environment:
          - REMOTE_SERVER_URL=<D3 vSOC URL>
          - PROXY_IDENTITY=<D3 vSOC Agent Security Token>
          - PYTHON_REMOTE_URL=http://<Docker Host IP>:<Docker Host Port>/
          - PYTHON_REMOTE_GUID=7e036a86dbee40d9913c3794e779eae4
          - SERVICE_DISPLAY_NAME=<Proxy Agent Display Name>
          - DOCKER_GID=<Docker Group ID>
          - DOCKER_PORT=<Docker Host Port>
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
      
      d3executor:
        image: "d3soar.azurecr.io/d3prod/d3executor:<D3 vSOC version>"
        ports:
          - "<Docker Host Port>:9090"
        restart: always
        environment:
          - EXECUTOR_GUID=7e036a86dbee40d9913c3794e779eae4
Step-by-Step Instructions to Modify the docker-compose.yml Template in Vim

Procedure

  1. Navigate into a directory to create the docker-compose.yml (we are using the same directory created in the Authenticating to Azure Container Registry):

    BASH
    cd D3ProxyAgent 
  2. Create the docker-compose.yml file using the text editor of your preference, such as nano, vim, or vi. For the purposes of this demonstration, let us use vim:

    BASH
    vim docker-compose.yml

    This will open and create the file in Normal Mode (Vim's default mode). When a file is opened in Vim, it will appear as follows:

    image 10 (3)-20241019-002047.png
  3. Press i to enter Insert Mode (the user will now be able to type or paste text in Vim).

  4. Copy and paste the template into Vim.

    1. Copy the template above from your browser or other text editor.

    2. Navigate back to the Vim terminal.

    3. Paste the template in Insert Mode:

      • Press Ctrl + Shift + V (in most terminals).
        Note: Ensure that the indentation remains correct after pasting.

      • Important: Every directive (such as services) should have exactly two spaces of indentation. The list items (like - "90:90") should not have leading spaces before the hyphen (-). Learn more about Docker Compose.

      • (Optional) If you encounter an error like the one below, check your docker-compose.yml spacing.

        Frame 8 (21)-20241019-002138.png
  5. Modify the template as necessary.

    • Replace the < > placeholders with specific values.

    • Replace the following placeholders (in Insert Mode) with appropriate values:

      • <D3 vSOC version>

      • <D3 vSOC URL>

      • <D3 vSOC Agent Security Token>

      • <Docker Host IP>

      • <Docker Host Port>

      • <Proxy Agent Display Name>

      • <Docker Group ID>

The details and meanings of the values can be found below.

  1. Exit Insert Mode once you have replaced all the placeholders.

    1. Press the Esc key to exit Insert Mode and return to Normal Mode.

  2. Save and quit the docker-compose.ymlfile.

    1. In Normal Mode, type:

      BASH
      :wq
    2. Press the Enter key to save and quit.

  3. Verify that all changes were saved correctly by using the following Linux command:

    BASH
    cat docker-compose.yml

Quick Summary of Commands:

  • i – Enter Insert Mode

  • Esc – Exit Insert Mode

  • :wq – Save and quit

  • Ctrl + Shift + C – Copy

  • Ctrl + Shift + V – Paste into Vim

  • cat docker-compose.yml – View file content

D3 VSOC VERSION – Replace <D3 vSOC version> with your vSOC version, which can be found on the D3 login page. For example, if you are using D3 vSOC release version 16.1.80.0, replace the <D3 vSOC version> placeholders within the d3agent and d3executor services to 16.1.80.0.
D3 VSOC URL – This the the vSOC URL, starting with https or http, and ending with /VSOC.
D3 VSOC AGENT SECURITY TOKEN – The D3 vSOC Agent Security Token can be generated by following these steps:

Frame 29 (13)-20250123-203919.png

a. Navigate to the the Configuration navigational tab.

b. Click on the Agent Management menu item on the left sidebar

c. Click on the + Generate Security Token button.

d. Select your site from the dropdown menu.

e. Click on the Generate Key button.

f. Click on the Copy button, then paste the security token into the docker-compose.yml file.

DOCKER HOST IP – The <Docker Host IP> refers to the private IP address of the Linux machine hosting Docker. You can find this address using the command ip addr show on Linux. Ensure that the port is accessible and not being used by any other program.
DOCKER HOST PORT – The <Docker Host Port> specified in the PYTHON_REMOTE_URL environment variable of the d3agent service must match the <Docker Host Port> specified in the ports mapping of the d3executor service. This ensures proper communication between the d3agent and d3executor services.
PROXY AGENT DISPLAY NAME – Input a descriptive name for this Agent, it displayed on vSOC.
DOCKER GROUP ID – Run the following command to obtain the <Docker Group ID>:

BASH
getent group docker | cut -d: -f3
Frame 6 (6)-20241017-035833.png
  1. Open a terminal and navigate to the directory where the docker-compose.yml file. Once there, execute the following command:

    BASH
    sudo docker compose up -d
  2. Upon successfully bringing up the Docker Compose services, your terminal will display outputs similar to the following:

    Frame 4 (3)-20240709-230040.png
Options for Running the Edited docker-compose.yml File
Option 1: Running All Services

To start all services defined in the docker-compose.yml in detached mode (in the background), run the following command:

BASH
sudo docker compose up -d

You may need to use sudo because Docker commands interact with system-level resources, such as the Docker daemon or sockets, which require elevated permissions.

Option 2: Starting a Specific Service (e.g., d3agent or d3executor)

If you only need to start one specific service, run the following commands:

BASH
sudo docker compose up d3agent -d 
sudo docker compose up d3executor -d
  • -d: Runs the service in detached mode, preventing it from blocking the terminal.

  • You can replace d3agent or d3executor with other service names defined in their docker-compose.yml file. These names may vary depending on your setup or specific requirements.

Option 3: Rebuilding and Restarting a Specific Service

If you have made changes to the service’s Docker image or dependencies, and need to rebuild and restart docker-compose.yml, run the following commands:

BASH
sudo docker compose up d3agent --build -d 
sudo docker compose up d3executor --build -d
  • --build: Forces Docker to rebuild the service’s image before starting it.

Docker Service Logs and Status Checks

Checking Service Logs

To view the logs for a specific service, run the following commands:

BASH
sudo docker compose logs d3agent 
sudo docker compose logs d3executor

For continuous log output, run the following command:

BASH
sudo docker compose logs -f d3agent
Checking the Status of All Running Containers

To view the status of all containers managed by your docker-compose.yml, run the following command:

BASH
docker compose ps
  • This command shows the status of the services, indicating which ones are running, stopped, or restarting.

  • See Learn more about Docker Compose for more details.

  1. Confirm the presence of your new agent.

    Frame 9 (43)-20250123-210722.png
    1. Navigate to the Configuration page.

    2. Click on the Agent Management module.

    3. Verify that the Agent Name matches the one specified in the docker-compose.yml file.

    4. Check the agent (connection) status and version. The agent version should match your D3 vSOC version.

    5. (Optional) Enter a description for your agent.

    6. Click on the Save button.

  2. (Optional) Troubleshoot via Docker Compose log commands.

    Frame 5 (4)-20241017-031517.png
  3. DOCKER COMPOSE LOGS To view a complete list of Docker Compose service logs, both logs for the d3executor and d3agent services, run the following command:

    BASH
     sudo docker compose logs  

    Ideally, only d3executor logs display—this confirms successful agent setup.


    D3EXECUTOR LOGS To view a list of d3executor service logs, run the following command:

    BASH
     sudo docker compose logs d3executor 

    D3AGENT LOGS To view a list of d3agent service logs, run the following command:

    BASH
     sudo docker compose logs d3agent

Automating D3 Agent and D3 Executor Deployment

The create_d3agent_file.sh Bash script automates the deployment of two necessary containers: d3agent and d3executor. It validates prerequisites, ensures Docker is installed and running, and authenticates with Google Cloud Container Registry using a configuration file. The script dynamically generates a Docker Compose file for the containers, prompts the user to start them, performs iterative health checks, and provides deployment success feedback or error diagnostics.

READER NOTE

Deployment automation for the D3 Agent and D3 Executor is supported beginning with D3 vSOC version 16.8.161.

Procedure

  1. Contact us to obtain the service_account_d3soar.json file required for authentication with D3's container registry.

  1. Place the service_account_d3soar.json file in the same directory as create_d3agent_file.sh and vars.conf.

create_d3agent_file.sh
CODE
#!/bin/bash
set -eu

# Define exit codes
EXIT_DOCKER_INSTALL_FAILED=20
EXIT_GCR_AUTH_FAILED=30

###########
# FUNCTIONS
###########

# Validates the provided URL to ensure it follows the HTTP/HTTPS format.
validate_url() {
  if [[ ! $1 =~ ^https?://.+ ]]; then
    echo "Invalid URL. Please enter a valid http/https URL."
    exit 1
  fi
}

# Validates the provided IP address to ensure it conforms to IPv4 format.
validate_ip() {
  if [[ ! $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Invalid IP address format. Please enter a valid IP."
    exit 1
  fi
}

# Validates the security token to ensure it is a 32-character lowercase alphanumeric string.
validate_token() {
  if [[ ! $1 =~ ^[a-z0-9]{32}$ ]]; then
    echo "Invalid token. Please enter a 32-character alphanumeric lowercase string."
    exit 1
  fi
}

# Validates the provided vSOC version to ensure it matches the required numeric format with four segments.
validate_version() {
  if [[ ! $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Invalid version. Please enter a version like 16.xx.xx.xx"
    exit 1
  fi
}

# Checks for available ports, starting at port 9090.
find_available_port() {
    local port=9090
    local max_attempts=100
    local attempt=1

    while ss -tuln | grep -q ":$port\b"; do
        if ((attempt >= max_attempts)); then
            echo "No available ports found after $max_attempts attempts."
            exit 1
        fi
        ((port++))
        ((attempt++))
    done
    echo "$port"
}

# Checks the operational status of specified Docker containers and reports issues.
check_container_status() {
    # Checks the agent container status
    container_agent_status=$(sudo docker ps --filter "name=$1" --format "{{.Names}} {{.Status}}" | grep -q "$1.*Up" && echo "running" || echo "not running")
    container_executor_status=$(sudo docker ps --filter "name=$2" --format "{{.Names}} {{.Status}}" | grep -q "$2.*Up" && echo "running" || echo "not running")

    # Sets the agent and executor status variables.
    agent_status=$container_agent_status
    executor_status=$container_executor_status

    # Checks whether the containers are in a "Restarting" state. If either container is in this state, the script outputs an error message and terminates.
    if sudo docker ps --filter "name=$1" --format "{{.Names}} {{.Status}}" | grep -q "$1.*Restarting"; then
        echo "installation failed, please check $1's log"
        exit 1
    fi
    if sudo docker ps --filter "name=$2" --format "{{.Names}} {{.Status}}" | grep -q "$2.*Restarting"; then
        echo "installation failed, please check $2's log"
        exit 1
    fi

    # Notifies the user of any container that is not in a running state.
    if [[ "$agent_status" == "not running" ]]; then
        echo "$1 container is not running"
    fi
    if [[ "$executor_status" == "not running" ]]; then
        echo "$2 container is not running"
    fi
}

######################################
# INSTALL DOCKER + AUTHENTICATE TO GCR
######################################

# Ensures Docker is installed and attempts automatic installation if missing.
if ! command -v docker >/dev/null 2>&1; then
    echo "Docker is not installed. Installing Docker..."
    
    # Installs Docker based on the helper script
    echo "This script will attempt to install Docker automatically by downloading and executing this helper script provided by Docker Inc: https://get.docker.com."
    read -p "Would you like to download and execute this script to install Docker automatically? (Y/N): " user_response
    
    if [[ $user_response == "y" || $user_response == "Y" ]]; then
        curl -fsSL https://get.docker.com -o get-docker.sh
        sudo sh ./get-docker.sh 
        sudo systemctl enable docker --now
        
        # Verifies whether Docker was installed successfully.
        if ! command -v docker >/dev/null 2>&1; then
            echo "Docker installation failed."
            exit $EXIT_DOCKER_INSTALL_FAILED
        fi
    else
        echo "Docker not installed. Please install manually and re-run this script."
        exit $EXIT_DOCKER_INSTALL_FAILED
    fi
fi

SERVICE_ACCOUNT_FILE="service_account_d3soar.json"

# Uses the service account file, if found, to log in to GCR. If not found or if login fails, exit with an error code and display an appropriate message.
if [ -f "$SERVICE_ACCOUNT_FILE" ]; then
    echo "Logging in to Google Cloud Container Registry using service account key..."
    LOGIN_OUTPUT=$(cat "$SERVICE_ACCOUNT_FILE" | sudo docker login -u _json_key --password-stdin https://gcr.io 2>&1)
    echo "$LOGIN_OUTPUT"
    
    # Checks for "Login Succeeded" in the output.
    if echo "$LOGIN_OUTPUT" | grep -q "Login Succeeded"; then
        echo "Generating Docker Compose file..."
    else
        echo "Docker login failed."
        exit $EXIT_GCR_AUTH_FAILED
    fi
else
    echo "Service account file $SERVICE_ACCOUNT_FILE not found. Please contact your D3 representative to obtain it."
    exit $EXIT_GCR_AUTH_FAILED
fi

#################################
# GENERATE docker-compose-d3.yaml
#################################

# Loads the vSOC URL and security token from vars.conf configuration file.
if [ -f "./vars.conf" ]; then
    source vars.conf
else
    echo "'vars.conf' doesn't exist. Create vars.conf with two line-separated key=value pairs: vsoc_url and security_token."
    exit 1
fi

# Validates that required variables are set.
if [[ -z "${vsoc_url:-}" || -z "${security_token:-}" ]]; then
  echo "Error: Missing required variables (vsoc_url, security_token). Verify vars.conf has these keys set."
  exit 1
fi

# Obtains the host machine's IP address.
host_ip=$(ip -o route get "8.8.8.8" 2>/dev/null | awk '{print $7}')

# Generates a unique GUID for the remote Python agent.
python_remote_guid=$(uuidgen | tr -d '-')

# Finds an available Docker port.
docker_port=$(find_available_port)

# Sets the agent display name.
agent_display_name="D3Agent - $host_ip"

# Retrieves the Docker GID.
docker_gid=$(getent group docker | cut -d: -f3)

# Ensures the vSOC URL is properly formatted with a trailing slash.
vsoc_url="${vsoc_url%/}/"  

# Validates the loaded configuration values.
validate_ip "$host_ip"
validate_token "$security_token"
validate_url "$vsoc_url"

# Constructs the full URL.
url="${vsoc_url}api/REST/GetD3Version"

# Fetches the content of the URL specified in $url.
html=$(curl -s -k "$url")

# Extracts the vSOC version number.
vsoc_version=$(echo "$html" | grep -oP 'D3 vSOC Version \K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')

# Verifies whether the vsoc_version value matches the expected format.
validate_version "$vsoc_version"

# Checks whether vsoc_version is empty. If so, prints an error and exits.
if [[ -z "$vsoc_version" ]]; then
    echo "Version information not found."
    exit 1
fi

# Generate unique names for the containers.
container_agent=d3agent_$RANDOM
container_executor=d3executor_$RANDOM

# Generates the Docker Compose YAML
cat <<EOF >docker-compose-d3.yml
services:
  d3agent:
    container_name: $container_agent
    image: "gcr.io/nimble-cortex-285618/d3prod/d3agent:${vsoc_version}"
    restart: always
    environment:
      - REMOTE_SERVER_URL=${vsoc_url}
      - PROXY_IDENTITY=${security_token}
      - PYTHON_REMOTE_URL=http://${host_ip}:${docker_port}/
      - PYTHON_REMOTE_GUID=${python_remote_guid}
      - SERVICE_DISPLAY_NAME=${agent_display_name}
      - DOCKER_GID=${docker_gid}
      - DOCKER_PORT=${docker_port}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  d3executor:
    container_name: $container_executor
    image: "gcr.io/nimble-cortex-285618/d3prod/d3executor:${vsoc_version}"
    ports:
      - "${docker_port}:9090"
    restart: always
    environment:
      - EXECUTOR_GUID=${python_remote_guid}
EOF

echo "A Docker Compose file for D3 Proxy Agent has been generated successfully: docker-compose-d3.yml"

# Prompts the user to start the containers.
read -p "Would you like to start the containers? (Y/N): " user_response

if [[ $user_response == "y" || $user_response == "Y" ]]; then
    # Attempts to bring up the Docker containers.
    sudo docker compose -f docker-compose-d3.yml up -d --remove-orphans || echo "Failed to bring up Docker containers. Verify the contents of 'docker-compose-d3.yml' and run 'sudo docker compose -f docker-compose-d3.yml up -d' to manually start the containers."

    echo "Checking container status..."
    counter=1

    # Performs up to 5 health checks on the containers. If any container fails, the loop exits early.
    while [ $counter -le 5 ]; do
        # Checks container statuses.
        check_container_status $container_agent $container_executor

        # Checks whether the agent container is running.
        if [[ "$agent_status" != "running" ]]; then
            echo Unhealthy Agent!
            break
        fi

        # Checks whether the executor container is running.
        if [[ "$executor_status" != "running" ]]; then
            echo Unhealthy Executor!
            break
        fi
        
        echo Health Check \#$counter/5 passed
        counter=$((counter + 1))

        sleep 5
    done

    # Checks final container statuses and print a success or failure message with troubleshooting suggestions.
    if [[ "$agent_status" != "running" ]] || [[ "$executor_status" != "running" ]]; then
      echo "Installation failed. You can check the container statuses with 'sudo docker compose -f docker-compose-d3.yml ps' or the container logs with 'sudo docker compose -f docker-compose-d3.yml logs'"
    else
      echo "Installation succesful! Log in to your VSOC instance at $vsoc_url to check the Agent Status from the UI."
    fi
   
else
    echo "Verify the contents of 'docker-compose-d3.yml' and run 'sudo docker compose -f docker-compose-d3.yml up -d' to manually start the containers."
fi

Save the code:
create_d3agent_file.txt

  1. Set up the vars.conf configuration file as follows:

TEXT
vsoc_url=<VSOC URL>
security_token=<Agent Token Generated in the UI>
Frame 28 (13)-20250103-014018.png
Frame 27 (9)-20250103-013419.png
  1. Execute the create_d3agent_file.sh script by running the following two commands:

    BASH
    chmod +x create_d3agent_file.sh
    ./create_d3agent_file.sh

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.