skip to Main Content

My objective is connect two different containers to get data, in other words:

  • I have an instance of OpenCTI working in my docker , and I can access it through my browser (http://localhost:8080).
  • Consequently, I am developing another one to get data from OpenCTI.

To connect both, I already created a docker network called "minharede".

However is not working.

The configuration of my containers is:

Docker-compose file of OpenCTI:

version: '3'
services:
  redis:
    image: redis:6.2.6
    restart: always
    volumes:
      - redisdata:/data
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.1
    volumes:
      - esdata:/usr/share/elasticsearch/data
    environment:
      - discovery.type=single-node
      - xpack.ml.enabled=false
    restart: always
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
  minio:
    image: minio/minio:RELEASE.2022-02-26T02-54-46Z
    volumes:
      - s3data:/data
    ports:
      - "9800:9800"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}    
    command: server /data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 30s
      timeout: 20s
      retries: 3
    restart: always
  rabbitmq:
    image: rabbitmq:3.9-management
    environment:
      - RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER}
      - RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS}
    volumes:
      - amqpdata:/var/lib/rabbitmq
    restart: always
  opencti:
    image: opencti/platform:5.2.1          
    environment:
      - NODE_OPTIONS=--max-old-space-size=8096
      - APP__PORT=8080
      - APP__ADMIN__EMAIL=${OPENCTI_ADMIN_EMAIL}
      - APP__ADMIN__PASSWORD=${OPENCTI_ADMIN_PASSWORD}
      - APP__ADMIN__TOKEN=${OPENCTI_ADMIN_TOKEN}
      - APP__APP_LOGS__LOGS_LEVEL=error
      - REDIS__HOSTNAME=redis
      - REDIS__PORT=6379
      - ELASTICSEARCH__URL=http://elasticsearch:9200
      - MINIO__ENDPOINT=minio
      - MINIO__PORT=9000
      - MINIO__USE_SSL=false
      - MINIO__ACCESS_KEY=${MINIO_ROOT_USER}
      - MINIO__SECRET_KEY=${MINIO_ROOT_PASSWORD}
      - RABBITMQ__HOSTNAME=rabbitmq
      - RABBITMQ__PORT=5672
      - RABBITMQ__PORT_MANAGEMENT=15672
      - RABBITMQ__MANAGEMENT_SSL=false
      - RABBITMQ__USERNAME=${RABBITMQ_DEFAULT_USER}
      - RABBITMQ__PASSWORD=${RABBITMQ_DEFAULT_PASS}
      - SMTP__HOSTNAME=${SMTP_HOSTNAME}
      - SMTP__PORT=25
      - PROVIDERS__LOCAL__STRATEGY=LocalStrategy
    ports:
      - "8080:8080"
    depends_on:
      - redis
      - elasticsearch
      - minio
      - rabbitmq
    restart: always
  worker:
    image: opencti/worker:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - WORKER_LOG_LEVEL=info
    depends_on:
      - opencti
    deploy:
      mode: replicated
      replicas: 3
    restart: always
  connector-history:
    image: opencti/connector-history:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_HISTORY_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=STREAM
      - CONNECTOR_NAME=History
      - CONNECTOR_SCOPE=history
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-export-file-stix:
    image: opencti/connector-export-file-stix:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_STIX_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
      - CONNECTOR_NAME=ExportFileStix2
      - CONNECTOR_SCOPE=application/json
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-export-file-csv:
    image: opencti/connector-export-file-csv:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_CSV_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
      - CONNECTOR_NAME=ExportFileCsv
      - CONNECTOR_SCOPE=text/csv
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-export-file-txt:
    image: opencti/connector-export-file-txt:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_EXPORT_FILE_TXT_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_EXPORT_FILE
      - CONNECTOR_NAME=ExportFileTxt
      - CONNECTOR_SCOPE=text/plain
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-import-file-stix:
    image: opencti/connector-import-file-stix:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_IMPORT_FILE_STIX_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_IMPORT_FILE
      - CONNECTOR_NAME=ImportFileStix
      - CONNECTOR_VALIDATE_BEFORE_IMPORT=true # Validate any bundle before import
      - CONNECTOR_SCOPE=application/json,text/xml
      - CONNECTOR_AUTO=true # Enable/disable auto-import of file
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
    restart: always
    depends_on:
      - opencti
  connector-import-document:
    image: opencti/connector-import-document:5.2.1
    environment:
      - OPENCTI_URL=http://opencti:8080
      - OPENCTI_TOKEN=${OPENCTI_ADMIN_TOKEN}
      - CONNECTOR_ID=${CONNECTOR_IMPORT_DOCUMENT_ID} # Valid UUIDv4
      - CONNECTOR_TYPE=INTERNAL_IMPORT_FILE
      - CONNECTOR_NAME=ImportDocument
      - CONNECTOR_VALIDATE_BEFORE_IMPORT=true # Validate any bundle before import
      - CONNECTOR_SCOPE=application/pdf,text/plain,text/html
      - CONNECTOR_AUTO=true # Enable/disable auto-import of file
      - CONNECTOR_ONLY_CONTEXTUAL=false # Only extract data related to an entity (a report, a threat actor, etc.)
      - CONNECTOR_CONFIDENCE_LEVEL=15 # From 0 (Unknown) to 100 (Fully trusted)
      - CONNECTOR_LOG_LEVEL=info
      - IMPORT_DOCUMENT_CREATE_INDICATOR=true
    restart: always
    depends_on:
      - opencti

networks: 
  default: 
    external: 
      name: minharede #network created for the purpose

volumes:
  esdata:
  s3data:
  redisdata:
  amqpdata:
    

Docker-Compose file Container B:

    version: '3.4'
    
    services:
      teste:
        image: teste
        build:
          context: .
          dockerfile: ./Dockerfile
    networks: 
      default: 
        external: 
          name: minharede  #docker network created for the purpose

The config.yml of container B is:

opencti:
  url: "http://localhost:8080"
  token: "xxxxxxxxxxxxxxxxxxxxxxxxxxx" #is hidden to post here

connector:
  id: "245b2de5-b85e-4236-bedd-97540b133ea2"
  type: "INTERNAL_ENRICHMENT"
  name: "osthreatenrichment"
  scope: "IPv4-Addr, IPv6-Addr, Domain-Name"
  auto: true
  confidence_level: 70 #From 0 (unknown) to 100 (Fully trusted)
  log_level: "info"

When I try to run my container B on Visual Code to test it (it’s connected to the docker), I get this error:

Exception has occurred: ValueError OpenCTI API is not reachable.
Waiting for OpenCTI API to start or check your configuration…

Anyone can helpe me?? Thank you guys!

(image attached)
API is not reachable

3

Answers


  1. Chosen as BEST ANSWER

    First of all, during debug in VSCode that is connected to the Docker, the container in development (Cntainer B) connects a default network, in my case was a network called "bridge" . Consequently, I wasn't getting a connection to the same network that container OpenCTI and to solve this I performed the reverse, I connected the container OpenCTI to the network "bridge" where my container in development is connected. After that, I went to check the IP address of the service in my container OpenCTI that I wanted get a connection from container B, and I changed the url from http://opencti:8080 to http://172.xx.x.x:8080(you only have to replace xx by the correct numbers of the IP address) and worked fine for me!!


  2. The compose reference has this example:

    services:
      some-service:
        networks:
         - some-network
         - other-network
    

    And it states:

    Networks to join, referencing entries under the top-level networks key.

    You need to specify the network definition at the top level of your compose file, and in your service definition you need to specify the named network.

    However that’s not the whole story. As @davidmaze suggests, it will be easier to accomplish this within one compose file rather than multiple. Docker compose treats each compose as a separate "app" and everything within a compose is "namespaced" to that app.


    In order to get what you want you’ll need to host your named network outside of the compose file. The docker network command is the direction you’d have to go in, but I think a whole tutorial on how to achieve this is outside the scope of an SO answer.

    In order to maintain a solution to this, every developer workstation would have to hold and maintain an identically configured named network which both compose-apps could join. This is counterproductive — the point of developing within a docker compose is to hold the entire development environment within the repository itself.

    In any case, the key component is building a named network on your workstation with docker network create <name> and then attaching to it within your compose file via the external attribute.

    https://docs.docker.com/compose/networking/#use-a-pre-existing-network (scroll up just a tad, the documentation site for docker misaligns by about 150px when an #anchor is loaded):

    If you want your containers to join a pre-existing network, use the external option:

    services:
      # ...
    networks:
      default:
        external:
          name: my-pre-existing-network
    
    Login or Signup to reply.
  3. You are using http://localhost:8080 as the target, which cannot work, as each container is its own localhost.

    opencti:
      url: "http://localhost:8080" # this should be the other services name
    

    Change it to the target container’s network alias (compose service name). In this case opencti.


    When I replicate your setup, I get a deprecation warning

    WARN[0000] network default: network.external.name is deprecated in favor of network.name 
    

    I have fixed this warning, and could successfully create the setup.

    First, I create the network:

    docker network create minharede
    

    Then, I create a dummy service in a.yaml and run docker compose -p a -f a.yaml up -d:

    # a.yaml
    services:
      my-svc:
        image: traefik/whoami
    networks:
      default:
        name: minharede
        external: true
    

    Finally, I create another service in a different file to curl for the network alias whoami of the service.

    # b.yaml
    services:
      curl:
        image: curlimages/curl
        command: -s my-svc
    networks:
      default:
        name: minharede
        external: true
    

    When, I run docker compose -p b -f b.yaml up I can see the following output.

    Attaching to curl_1
    curl_1  | Hostname: d63e37dd5363
    curl_1  | IP: 127.0.0.1
    curl_1  | IP: 172.22.0.2
    curl_1  | RemoteAddr: 172.22.0.3:38960
    curl_1  | GET / HTTP/1.1
    curl_1  | Host: my-svc
    curl_1  | User-Agent: curl/7.82.0-DEV
    curl_1  | Accept: */*
    curl_1  | 
    curl_1 exited with code 0
    

    So what you are trying to do is certainly possible. You are just using the wrong hostname. In my example, you can see the service name in the compose file of the service I am trying to curl is my-svc. That’s also what I am using for the hostname in the curl command.


    You could actually simplify this by not using an external network for a but still reference a's default network as external in b.

    # a.yaml
    networks:
      default:
        name: minharede
    
    # b.yaml
    networks:
      default:
        name: minharede
        external: true
    

    Then you only need to make sure you start a before b.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search