Skip to content

Commit

Permalink
Merge pull request #304 from alcastronic/add-bloodhound-community
Browse files Browse the repository at this point in the history
Add bloodhound community
  • Loading branch information
MarcOverIP committed Nov 17, 2023
2 parents 0886be7 + 97974de commit 5e49ef6
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 11 deletions.
24 changes: 24 additions & 0 deletions elkserver/.env.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ NEO4J_AUTH=neo4j/{{NEO4J_PASSWORD}}
NEO4J_dbms_memory_heap_initial__size={{NEO4J_MEMORY}}
NEO4J_dbms_memory_heap_max__size={{NEO4J_MEMORY}}
NEO4J_dbms_memory_pagecache_size={{NEO4J_MEMORY}}
# Allow upgrades of neo4j data (useful when importing external data)
NEO4J_ALLOW_UPGRADE=true

## Bloodhound Community Edition specific variables
# Select the image tag to use (latest, edge, or version number)
BLOODHOUND_TAG=latest
# Postgres auth configuration
POSTGRES_USER=bloodhound
POSTGRES_PASSWORD={{PGSQL_PASSWORD}}
POSTGRES_DATABASE=bloodhound
# Data directory for neo4j
# Uncomment if you want a filesystem mount for your neo4j data in the current directory
#NEO4J_DATA_MOUNT=./neo4j/data
# Port forwards
# You can also use the form "127.0.0.1:8080" if you aren't running in a virtual environment (like WSL2)
# and only want this accessible on localhost
BLOODHOUND_PORT=127.0.0.1:8080
#POSTGRES_PORT=5432
NEO4J_DB_PORT=7687
NEO4J_WEB_PORT=7474

# BloodHound Configuration Parameters
# Uncomment if you want to disable cypher quality control
#bhe_disable_cypher_qc=false


## Variables for NGINX certificates mounts
Expand Down
93 changes: 91 additions & 2 deletions elkserver/install-elkserver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ FIXEDMEMORY="no"
DOCKERCONFFILE="redelk-full.yml"
DOCKERENVFILE=".env"
DOCKERENVTMPLFILE=".env.tmpl"
BLOODHOUND_APP_CONFIG="./mounts/bloodhound-config/bloodhound.config.json"

printf "[*] `date +'%b %e %R'` $INSTALLER - Starting installer\n" > $LOGFILE 2>&1
echo ""
Expand Down Expand Up @@ -43,7 +44,7 @@ printinstallsummary() {
echo "[*] No 'limited' parameter found. Going for the full RedELK installation including: " | tee -a $LOGFILE
echo "- RedELK"
echo "- Jupyter notebooks"
echo "- BloodHound / Neo4j"
echo "- BloodHound / Neo4j / Postgres"
fi
echo ""
echo "5 Seconds to abort"
Expand Down Expand Up @@ -481,6 +482,76 @@ if [ ${WHATTOINSTALL} = "full" ]; then
echo "[*] Neo4j password in docker template already defined - skipping" | tee -a $LOGFILE
NEO4J_PASSWORD=$(grep -E ^NEO4J_AUTH= .env|awk -Fneo4j/ '{print $2}')
fi
# check if Neo4J password is already generated and set in bloodhound config as it can not be set through env.
# https://github.com/SpecterOps/BloodHound/issues/9
if (grep "{{NEO4J_PASSWORD}}" $BLOODHOUND_APP_CONFIG > /dev/null); then
# do not regenerate the password as it should already be set
echo "[*] Setting neo4j password" | tee -a $LOGFILE
sed -E -i.bak "s/\{\{NEO4J_PASSWORD\}\}/${NEO4J_PASSWORD}/g" ${BLOODHOUND_APP_CONFIG} >> $LOGFILE 2>&1
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not set postgresql password (Error Code: $ERROR)." | tee -a $LOGFILE
fi
fi

# check if Postgres password is already generated and set in Docker env.
if (grep "{{PGSQL_PASSWORD}}" $DOCKERENVFILE > /dev/null); then
POSTGRES_PASSWORD=$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c32)

echo "[*] Setting postgresql password" | tee -a $LOGFILE
sed -E -i.bak "s/\{\{PGSQL_PASSWORD\}\}/${POSTGRES_PASSWORD}/g" ${DOCKERENVFILE} >> $LOGFILE 2>&1
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not set postgresql password (Error Code: $ERROR)." | tee -a $LOGFILE
fi
else
echo "[*] Postgresql password in docker template already defined - skipping" | tee -a $LOGFILE
POSTGRES_PASSWORD=$(grep -E ^POSTGRES_PASSWORD= .env|awk -F= '{print $2}')
fi
# check if Postgres password is already set in bloodhound config as it can not be set through env.
# https://github.com/SpecterOps/BloodHound/issues/9
if (grep "{{PGSQL_PASSWORD}}" $BLOODHOUND_APP_CONFIG > /dev/null); then
# do not regenerate the password as it should already be set
echo "[*] Setting postgresql password" | tee -a $LOGFILE
sed -E -i.bak "s/\{\{PGSQL_PASSWORD\}\}/${POSTGRES_PASSWORD}/g" ${BLOODHOUND_APP_CONFIG} >> $LOGFILE 2>&1
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not set postgresql password (Error Code: $ERROR)." | tee -a $LOGFILE
fi
fi

# check if Bloodhound admin password is already generated and set in bloodhound app config as it can not be set through env.
# https://github.com/SpecterOps/BloodHound/issues/9
if (grep "{{BLOODHOUND_PASSWORD}}" $BLOODHOUND_APP_CONFIG > /dev/null); then
BLOODHOUND_PASSWORD=$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c32)

echo "[*] Setting bloodhound password" | tee -a $LOGFILE
sed -E -i.bak "s/\{\{BLOODHOUND_PASSWORD\}\}/${BLOODHOUND_PASSWORD}/g" ${BLOODHOUND_APP_CONFIG} >> $LOGFILE 2>&1
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not set bloodhound password (Error Code: $ERROR)." | tee -a $LOGFILE
fi
else
echo "[*] Bloodhound password in bloodhound config already defined - skipping" | tee -a $LOGFILE
BLOODHOUND_PASSWORD=$(grep -E '"password":' ${BLOODHOUND_APP_CONFIG}|awk -F " \"" '{print $3}'|sed -e "s/\",//")
fi


# check if Bloodhound admin email is already generated and set in bloodhound app config as it can not be set through env.
# https://github.com/SpecterOps/BloodHound/issues/9
if (grep "{{BLOODHOUND_ADMIN_EMAIL}}" $BLOODHOUND_APP_CONFIG > /dev/null); then
BLOODHOUND_ADMIN_EMAIL=$(cat ./mounts/redelk-config/etc/redelk/config.json | jq -r .redelkserver_letsencrypt.le_email)

echo "[*] Setting bloodhound password" | tee -a $LOGFILE
sed -E -i.bak "s/\{\{BLOODHOUND_ADMIN_EMAIL\}\}/${BLOODHOUND_ADMIN_EMAIL}/g" ${BLOODHOUND_APP_CONFIG} >> $LOGFILE 2>&1
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not set bloodhound admin email (Error Code: $ERROR)." | tee -a $LOGFILE
fi
else
echo "[*] Bloodhound admin e-mail in bloodhound config already defined - skipping" | tee -a $LOGFILE
BLOODHOUND_ADMIN_EMAIL=$(grep -E '"email_address":' ${BLOODHOUND_APP_CONFIG}|awk -F " \"" '{print $3}'|sed -e "s/\"//")
fi
fi

echo "[*] Setting permissions on redelk base cron job" | tee -a $LOGFILE
Expand Down Expand Up @@ -614,13 +685,25 @@ if [ ${WHATTOINSTALL} = "limited" ]; then
if [ $ERROR -ne 0 ]; then
echo "[X] Could not adjust Nginx config (Error Code: $ERROR)." | tee -a $LOGFILE
fi
# commenting out the bloodhound location template
sed -i 's/^\s*include conf.d\/full.bloodhound-conf;\s*$/ # include conf.d\/full.bloodhound-conf;/g' ./mounts/nginx-config/default.conf.template
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not adjust Nginx config (Error Code: $ERROR)." | tee -a $LOGFILE
fi
else
echo "[*] Adjusting Nginx config file" | tee -a $LOGFILE
sed -i 's/^\s*#\s*include conf.d\/full.location-conf;\s*$/ include conf.d\/full.location-conf;/g' ./mounts/nginx-config/default.conf.template
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not adjust Nginx config (Error Code: $ERROR)." | tee -a $LOGFILE
fi
# re-enabling the bloodhound location template
sed -i 's/^\s*#\s*include conf.d\/full.bloodhound-conf;\s*$/ include conf.d\/full.bloodhound-conf;/g' ./mounts/nginx-config/default.conf.template
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Could not adjust Nginx config (Error Code: $ERROR)." | tee -a $LOGFILE
fi
fi

echo "[*] Linking docker-compose.yml to the docker file used" | tee -a $LOGFILE
Expand All @@ -640,7 +723,12 @@ echo "CredHtaccessPassword = \"$CREDS_redelk\"" >> redelk_passwords.cfg && \
echo "CredESUsername = \"elastic\"" >> redelk_passwords.cfg && \
echo "CredESPassword = \"$ELASTIC_PASSWORD\"" >> redelk_passwords.cfg && \
echo "CredNeo4jUsername = \"neo4j\"" >> redelk_passwords.cfg && \
echo "CredNeo4jPassword = \"$NEO4J_PASSWORD\"" >> redelk_passwords.cfg
echo "CredNeo4jPassword = \"$NEO4J_PASSWORD\"" >> redelk_passwords.cfg && \
echo "CredBloodhoundAdminEmail = \"$BLOODHOUND_ADMIN_EMAIL\"" >> redelk_passwords.cfg && \
echo "CredBloodhoundUsername = \"admin\"" >> redelk_passwords.cfg && \
echo "CredBloodhoundPassword = \"$BLOODHOUND_PASSWORD\"" >> redelk_passwords.cfg && \
echo "CredPostgresUsername = \"bloodhound\"" >> redelk_passwords.cfg && \
echo "CredPostgresPassword = \"$POSTGRES_PASSWORD\"" >> redelk_passwords.cfg
ERROR=$?
if [ $ERROR -ne 0 ]; then
echo "[X] Error creating password file for easy reference (Error Code: $ERROR)." | tee -a $LOGFILE
Expand Down Expand Up @@ -712,6 +800,7 @@ if [ $DRYRUN == "no" ]; then
echo " - Main RedELK Kibana interface on port 443 (user: redelk, pass:$CREDS_redelk)" | tee -a $LOGFILE
if [ ${WHATTOINSTALL} != "limited" ]; then
echo " - Jupyter notebooks on /jupyter (user: redelk, pass:$CREDS_redelk)" | tee -a $LOGFILE
echo " - Bloodhound community edition on https port 8443 (user: admin, pass:$BLOODHOUND_PASSWORD)" | tee -a $LOGFILE
echo " - Neo4J Browser port 7473 (user: neo4j, pass:$NEO4J_PASSWORD)" | tee -a $LOGFILE
echo " - Neo4J using the BloodHound app on port 7687 (user: neo4j, pass:$NEO4J_PASSWORD)" | tee -a $LOGFILE
fi
Expand Down
30 changes: 30 additions & 0 deletions elkserver/mounts/bloodhound-config/bloodhound.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"version": 1,
"bind_addr": "0.0.0.0:8080",
"metrics_port": ":2112",
"root_url": "http://127.0.0.1:8080/",
"work_dir": "/opt/bloodhound/work",
"log_level": "INFO",
"log_path": "bloodhound.log",
"features": {
"enable_auth": true
},
"tls": {
"cert_file": "",
"key_file": ""
},
"database": {
"connection": "user=bloodhound password={{PGSQL_PASSWORD}} dbname=bloodhound host=redelk-bloodhound-postgres"
},
"neo4j": {
"connection": "neo4j://neo4j:{{NEO4J_PASSWORD}}@redelk-bloodhound-neo4j:7687/"
},
"collectors_base_path": "/etc/bloodhound/collectors",
"default_admin": {
"principal_name": "admin",
"password": "{{BLOODHOUND_PASSWORD}}",
"first_name": "Bloodhound",
"last_name": "Admin",
"email_address": "{{BLOODHOUND_ADMIN_EMAIL}}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"\n",
"\n",
"if __name__ == \"__main__\":\n",
" greeter = HelloWorldExample(\"bolt://redelk-bloodhound:7687\", CredNeo4jUsername, CredNeo4jPassword)\n",
" greeter = HelloWorldExample(\"bolt://redelk-bloodhound-neo4j:7687\", CredNeo4jUsername, CredNeo4jPassword)\n",
" greeter.print_greeting(\"hello, world\")\n",
" greeter.close()"
]
Expand Down
1 change: 1 addition & 0 deletions elkserver/mounts/nginx-config/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,5 @@ server {
include conf.d/full.location-conf;
}

include conf.d/full.bloodhound-conf;
# include conf.d/full.neo4j-conf;
62 changes: 62 additions & 0 deletions elkserver/mounts/nginx-config/full.bloodhound-conf.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
upstream bloodhound_app {
server redelk-bloodhound-app:8080;
}

server {
listen 8443 ssl http2;

#server_name ${EXTERNAL_DOMAIN};
server_tokens off;

root /var/www/html;
#auth_basic "Restricted Access";
#auth_basic_user_file /etc/nginx/conf.d/htpasswd.users;
index index.html index.htm;
autoindex on;

ssl_certificate ${TLS_NGINX_CRT_PATH};
ssl_certificate_key ${TLS_NGINX_KEY_PATH};
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;

# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

ssl_dhparam /etc/nginx/conf.d/ssl-dhparams.pem;

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;

# OCSP stapling
#ssl_stapling on;
#ssl_stapling_verify on;

# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate ${TLS_NGINX_CA_PATH};

location / {
#auth_basic "Restricted Access";
#auth_basic_user_file /etc/nginx/conf.d/htpasswd.users;


proxy_pass http://bloodhound_app;
proxy_set_header Host $host;

# Proxy headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

# Proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
4 changes: 2 additions & 2 deletions elkserver/mounts/nginx-config/full.location-conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ location /neo4jbrowser {
return 301 http://$host:7474;
# auth_basic "Restricted Access";
# auth_basic_user_file /etc/nginx/conf.d/htpasswd.users;
# proxy_pass http://redelk-bloodhound:7474/browser;
# proxy_pass http://redelk-bloodhound-neo4j:7474/browser;
}

location /jupyter {
Expand All @@ -20,4 +20,4 @@ location /jupyter {
proxy_set_header Upgrade "websocket";
proxy_set_header Connection "Upgrade";
proxy_read_timeout 86400;
}
}
2 changes: 1 addition & 1 deletion elkserver/mounts/nginx-config/full.neo4j-conf.template
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

upstream neo4j_bolt {
server redelk-bloodhound:7687;
server redelk-bloodhound-neo4j:7687;
}

server {
Expand Down

0 comments on commit 5e49ef6

Please sign in to comment.