By Adrian | May 7, 2020
Docker is something that i’ve not fully embraced to date, I know, I know… I’m a little late off the mark, but as I get to know Docker more, I can see that it has some worthwhile advantages for me in some of the projects I use and generally getting to know technology is never a bad thing. For instance, why spin up a single server for a service that only has 1 of the 65535 ports used when 99% of the time that server will most likely be idle. Docker gives you the ability to really utilise a host.
Recently I have been taking a look at OpenCTI in Docker and added in Traefik as a reverse proxy, and thought that I would do the same for a Docker/Cortex stack.
The best part about using Traefik is that it handles the Reverse Proxy and all the certificate requirements for you. I am using AWS Route53 via DNS challenge, but you can just as easily use a different DNS provider and/or HTTP challenge.
For this particular setup, there are a few pre-requisites required.
- A Linux host setup with Docker and Docker-Compose
- AWS Route53 for DNS challenge
- Appropriate AWS user account with manage DNS access
- A populated
.env
file
The .env
Environment File
To avoid hard coding certain items, I am using a .env
file that is placed in the same location as the docker-compose.yml
file.
Leave the CORTEX_KEY
empty at this time. We need to configure a Cortex user first and generate the API key.
CORTEX_KEY=[API KEY OF CORTEX USER]
AWS_HOSTED_ZONE_ID=[YOUR ROUTE53 DNS Zone ID]
AWS_ACCESS_KEY_ID=[AWS ACCESS KEY FOR A ROUTE53 USER]
AWS_SECRET_ACCESS_KEY=[AWS SECRET ACCESS KEY FOR A ROUTE53 USER]
LE_EMAIL=[YOUR EMAIL ADDRESS FOR LETS ENCRYPT]
The docker-compose.yml
file
Here is the docker-compose.yml
file that I used. It is coded to use the following services:
- Elasticsearch 6.8.8
- Cortex 3.0.1
- TheHive 3.4.1
- Traefik 2.2
We need to present the Cortex, TheHive and Elasticsearch services to the backend
network so they can all talk to each other. We are making the Cortex and TheHive services accessible via Traefik. Any traffic that comes in on port 80 will be automatically redirected to port 443 on the frontend, and Traefik will make the connection to the applications ports (9001 and 9000 respectively).
So we don’t run into issues with Lets Encrypt limits, I start by setting the - --certificatesResolvers.mytlschallenge.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory
command for the Traefik service, this way we are testing our setup out with time valid but browser invalid Lets Encrypt certificates. Once you have confirmed that everything is ok, this can be removed to generate fully fledged Lets Encrypt certificates.
Note: There are a few references to example.com
which will need to be updated to suit your environment. Once everything is setup, you will be able to access the following hosts in your browser. To avoid any conflicts with my other instances of TheHive/Cortex that I’m currently running, ive added docker into the hostname.
url | service |
---|---|
https://lb.example.com | Traefik dashboard |
https://thehivedocker.example.com | TheHive console |
https://cortexdocker.example.com | Cortex console |
Here is the yml
file.
version: "3"
services:
elasticsearch:
image: elasticsearch:6.8.8
environment:
- http.host=0.0.0.0
- discovery.type=single-node
ulimits:
nofile:
soft: 65536
hard: 65536
networks:
- backend
cortex:
image: thehiveproject/cortex:3.0.1
depends_on:
- elasticsearch
- traefik
networks:
- proxy
- backend
labels:
- "traefik.enable=true"
- "traefik.http.routers.cortexdocker.entrypoints=https"
- "traefik.http.routers.cortexdocker.rule=Host(`cortexdocker.example.com`)"
- "traefik.http.routers.cortexdocker.service=cortexdocker"
- "traefik.http.routers.cortexdocker.tls=true"
- "traefik.http.services.cortexdocker.loadbalancer.server.port=9001"
- "traefik.http.routers.cortexdocker.tls.certresolver=mytlschallenge"
- "traefik.http.routers.cortexdocker_http.entrypoints=http"
- "traefik.http.routers.cortexdocker_http.rule=Host(`cortexdocker.example.com`)"
- "traefik.http.routers.cortexdocker_http.middlewares=traefik-redirectscheme"
- "traefik.http.middlewares.traefik-redirectscheme.redirectscheme.scheme=https"
thehive:
image: thehiveproject/thehive:3.4.1
depends_on:
- elasticsearch
- cortex
- traefik
command:
--cortex-port 9001
--cortex-key ${CORTEX_KEY}
networks:
- proxy
- backend
labels:
- "traefik.enable=true"
- "traefik.http.routers.thehivedocker.entrypoints=https"
- "traefik.http.routers.thehivedocker.rule=Host(`thehivedocker.example.com`)"
- "traefik.http.routers.thehivedocker.service=thehivedocker"
- "traefik.http.routers.thehivedocker.tls=true"
- "traefik.http.services.thehivedocker.loadbalancer.server.port=9000"
- "traefik.http.routers.thehivedocker.tls.certresolver=mytlschallenge"
- "traefik.http.routers.thehivedocker_http.entrypoints=http"
- "traefik.http.routers.thehivedocker_http.rule=Host(`thehivedocker.example.com`)"
- "traefik.http.routers.thehivedocker_http.middlewares=traefik-redirectscheme"
- "traefik.http.middlewares.traefik-redirectscheme.redirectscheme.scheme=https"
traefik:
image: traefik:v2.2
environment:
- AWS_HOSTED_ZONE_ID=${AWS_HOSTED_ZONE_ID}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
restart: always
container_name: traefik
ports:
- "80:80"
- "443:443"
command:
- --api.insecure=true # set to 'false' on production
- --api.dashboard=true
- --api.debug=false
- --log.level=DEBUG
- --providers.docker=true
- --providers.docker.swarmMode=false
- --providers.docker.exposedbydefault=false
- --providers.docker.network=proxy
- --entrypoints.http.address=:80
- --entrypoints.https.address=:443
- --certificatesResolvers.mytlschallenge.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # Generates LE test certificates. Can be removed for production
- --certificatesResolvers.mytlschallenge.acme.dnsChallenge=true
- --certificatesResolvers.mytlschallenge.acme.dnsChallenge.provider=route53
- --certificatesresolvers.mytlschallenge.acme.email=${LE_EMAIL}
- --certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json
volumes:
- "letsencrypt:/letsencrypt"
- /var/run/docker.sock:/var/run/docker.sock
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.entrypoints=https"
- "traefik.http.routers.api.rule=Host(`lb.example.com`)"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.tls=true"
- "traefik.http.services.api.loadbalancer.server.port=8080"
- "traefik.http.routers.api.tls.certresolver=mytlschallenge"
- "traefik.http.routers.api_http.entrypoints=http"
- "traefik.http.routers.api_http.rule=Host(`lb.example.com`)"
- "traefik.http.routers.api_http.middlewares=traefik-redirectscheme"
- "traefik.http.middlewares.traefik-redirectscheme.redirectscheme.scheme=https"
networks:
backend:
proxy:
external: true
volumes:
letsencrypt:
With both the .env
file and docker-compose.yml
file created you can start it by using the following command.
env $(cat .env | grep ^[A-Z] | xargs) docker-compose up -d
# Output
Starting traefik ... done
Creating thehivedocker_elasticsearch_1 ... done
Creating thehivedocker_cortex_1 ... done
Creating thehivedocker_thehive_1 ... done
Give the setup a few minutes to start fully before accessing.
Initial Setup
Now that we have clean installations of TheHive and Cortex we need to do a few initial items on each to round it out
TheHive
Access https://thehivedocker.example.com
and press Update Database
.
Create your admin user
Login to TheHive. You will notice in the lower right that the Cortex Brain icon
has a red circle. This means that the integration is broken at the moment.
You can also confirm this by checking the About
screen. You should see an AUTH_ERROR
. This is normal at this time.
Cortex
Access https://cortexdocker.example.com
and press Update Database
. Note this is identical to the step performed for TheHive.
Create the main orgadmin
account. This account is used to manage organizations within Cortex.
Login to Cortex. We need to create a new organization. Press the Add organization
button and complete the details.
Now we need to create a few users for the new organization. Select Users
then Add User
from the top right hand side of the page.
Complete the details as follows:
- The username
- The Fullname of the user
- The orginization the user will belong to. Ensure the org you just created is setup
- The role the account has. Ensure
read, analyze, orgadmin
is selected - Press Save.
Once the account has been created, select New Password
on the users screen.
Create a second user account against the same organization. This time, give it the read, analyze
roles. This account will be what we use to connect TheHive to Cortex.
There is no need to set a password for this user, however we need to Create API Key
and select Reveal
. Next Copy
this API key.
Back in our .env
file, paste in the Cortex API key value to the CORTEX_KEY
variable.
Additional Steps
With the .env
file updated with our Cortex API key, we need to rerun Docker-Compose which will detect the changes that have been made.
env $(cat .env | grep ^[A-Z] | xargs) docker-compose up -d
# Output
traefik is up-to-date
thehivedocker_elasticsearch_1 is up-to-date
thehivedocker_cortex_1 is up-to-date
Recreating thehivedocker_thehive_1 ... done
Relogin to TheHive. Integration should now be working.
From here its just a matter of enabling any Analyzers
and/or Responders
from the Cortex console that are required.