From b39c8c1f1f19cf9a62a5a3a54438817d84b84853 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Fri, 7 May 2021 11:02:23 -0400 Subject: [PATCH 01/76] exit after 50 tries if manager cant connect to iteself via salt --- salt/common/tools/sbin/soup | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/salt/common/tools/sbin/soup b/salt/common/tools/sbin/soup index 77a2b6018..620737c16 100755 --- a/salt/common/tools/sbin/soup +++ b/salt/common/tools/sbin/soup @@ -802,7 +802,7 @@ else systemctl start salt-master # Testing that that salt-master is up by checking that is it connected to itself - retry 50 10 "salt-call state.show_top -l error" + retry 50 10 "salt-call state.show_top -l error" || exit 1 echo "" echo "Ensuring python modules for Salt are installed and patched." @@ -834,6 +834,10 @@ else echo "" echo "Starting Salt Master service." systemctl start salt-master + + # Testing that that salt-master is up by checking that is it connected to itself + retry 50 10 "salt-call state.show_top -l error" || exit 1 + echo "Running a highstate. This could take several minutes." salt-call state.highstate -l info queue=True postupgrade_changes From 71032150c5a08c6889e828b6500c79a3cd86929f Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 21 May 2021 17:27:00 -0400 Subject: [PATCH 02/76] Add secure HTTP headers to all SO application responses to reduce exposure to browser and other HTTP-related vulnerabilities --- salt/nginx/etc/nginx.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/salt/nginx/etc/nginx.conf b/salt/nginx/etc/nginx.conf index ea820442b..e9f67e065 100644 --- a/salt/nginx/etc/nginx.conf +++ b/salt/nginx/etc/nginx.conf @@ -149,6 +149,12 @@ http { root /opt/socore/html; index index.html; + add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' https: data:; frame-ancestors 'self'"; + add_header X-Frame-Options SAMEORIGIN; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options nosniff; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; + ssl_certificate "/etc/pki/nginx/server.crt"; ssl_certificate_key "/etc/pki/nginx/server.key"; ssl_session_cache shared:SSL:1m; From 0572ea4095b7388d7d88c8e4740be18a56fb73ab Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 21 May 2021 17:27:11 -0400 Subject: [PATCH 03/76] Fail curl command if a failing status code is returned by the remote server --- salt/common/tools/sbin/so-image-common | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/common/tools/sbin/so-image-common b/salt/common/tools/sbin/so-image-common index be5a327f0..47b04f241 100755 --- a/salt/common/tools/sbin/so-image-common +++ b/salt/common/tools/sbin/so-image-common @@ -128,7 +128,7 @@ update_docker_containers() { mkdir -p $SIGNPATH >> "$LOG_FILE" 2>&1 # Let's make sure we have the public key - retry 50 10 "curl -sSL https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/master/KEYS -o $SIGNPATH/KEYS" >> "$LOG_FILE" 2>&1 + retry 50 10 "curl -f -sSL https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/master/KEYS -o $SIGNPATH/KEYS" >> "$LOG_FILE" 2>&1 result=$? if [[ $result -eq 0 ]]; then cat $SIGNPATH/KEYS | gpg --import - >> "$LOG_FILE" 2>&1 @@ -151,7 +151,7 @@ update_docker_containers() { retry 50 10 "docker pull $CONTAINER_REGISTRY/$IMAGEREPO/$image" >> "$LOG_FILE" 2>&1 # Get signature - retry 50 10 "curl -A '$CURLTYPE/$CURRENTVERSION/$OS/$(uname -r)' https://sigs.securityonion.net/$VERSION/$i:$VERSION$IMAGE_TAG_SUFFIX.sig --output $SIGNPATH/$image.sig" >> "$LOG_FILE" 2>&1 + retry 50 10 "curl -f -A '$CURLTYPE/$CURRENTVERSION/$OS/$(uname -r)' https://sigs.securityonion.net/$VERSION/$i:$VERSION$IMAGE_TAG_SUFFIX.sig --output $SIGNPATH/$image.sig" >> "$LOG_FILE" 2>&1 if [[ $? -ne 0 ]]; then echo "Unable to pull signature file for $image" >> "$LOG_FILE" 2>&1 exit 1 From e2d5102a0e70f8f209b46e385031978fc9328390 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 24 May 2021 10:13:29 -0400 Subject: [PATCH 04/76] changes for script to auth to elastic --- salt/common/init.sls | 9 ++++++++ salt/common/tools/sbin/so-elastic-clear | 6 ++--- .../tools/sbin/so-elasticsearch-indices-list | 2 +- .../tools/sbin/so-elasticsearch-indices-rw | 4 ++-- .../sbin/so-elasticsearch-pipeline-stats | 4 ++-- .../tools/sbin/so-elasticsearch-pipeline-view | 4 ++-- .../sbin/so-elasticsearch-pipelines-list | 4 ++-- .../tools/sbin/so-elasticsearch-shards-list | 2 +- .../sbin/so-elasticsearch-template-remove | 2 +- .../tools/sbin/so-elasticsearch-template-view | 4 ++-- .../sbin/so-elasticsearch-templates-list | 4 ++-- salt/common/tools/sbin/so-index-list | 2 +- salt/common/tools/sbin/soup | 4 ++-- salt/firewall/portgroups.yaml | 3 +++ salt/utility/bin/crossthestreams | 6 ++--- salt/utility/bin/eval | 4 ++-- salt/utility/init.sls | 23 +++++++++++++++---- 17 files changed, 57 insertions(+), 30 deletions(-) diff --git a/salt/common/init.sls b/salt/common/init.sls index 33a8b9984..948adee99 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -2,6 +2,8 @@ {% if sls in allowed_states %} {% set role = grains.id.split('_') | last %} +{% set ELASTICUSER = salt['pillar.get']('elasticsearch:auth:user', '' ) %} +{% set ELASTICPASS = salt['pillar.get']('elasticsearch:auth:pass', '' ) %} # Remove variables.txt from /tmp - This is temp rmvariablesfile: @@ -178,6 +180,13 @@ utilsyncscripts: - file_mode: 755 - template: jinja - source: salt://common/tools/sbin + - defaults: + ELASTICCURL: "curl" +{% if salt['pillar.get']('elasticsearch:auth_enabled', False) %} + - context: + ELASTICCURL: "curl --user {{ELASTICUSER}}:{{ELASTICPASS}}" +{% endif %} + {% if role in ['eval', 'standalone', 'sensor', 'heavynode'] %} # Add sensor cleanup diff --git a/salt/common/tools/sbin/so-elastic-clear b/salt/common/tools/sbin/so-elastic-clear index 4c7271272..56b5c3d2c 100755 --- a/salt/common/tools/sbin/so-elastic-clear +++ b/salt/common/tools/sbin/so-elastic-clear @@ -50,7 +50,7 @@ done if [ $SKIP -ne 1 ]; then # List indices echo - curl -k -L https://{{ NODEIP }}:9200/_cat/indices?v + {{ ELASTICCURL }} -k -L https://{{ NODEIP }}:9200/_cat/indices?v echo # Inform user we are about to delete all data echo @@ -89,10 +89,10 @@ fi # Delete data echo "Deleting data..." -INDXS=$(curl -s -XGET -k -L https://{{ NODEIP }}:9200/_cat/indices?v | egrep 'logstash|elastalert|so-' | awk '{ print $3 }') +INDXS=$({{ ELASTICCURL }} -s -XGET -k -L https://{{ NODEIP }}:9200/_cat/indices?v | egrep 'logstash|elastalert|so-' | awk '{ print $3 }') for INDX in ${INDXS} do - curl -XDELETE -k -L https://"{{ NODEIP }}:9200/${INDX}" > /dev/null 2>&1 + {{ ELASTICCURL }} -XDELETE -k -L https://"{{ NODEIP }}:9200/${INDX}" > /dev/null 2>&1 done #Start Logstash/Filebeat diff --git a/salt/common/tools/sbin/so-elasticsearch-indices-list b/salt/common/tools/sbin/so-elasticsearch-indices-list index c9df67a25..b5cd1b359 100755 --- a/salt/common/tools/sbin/so-elasticsearch-indices-list +++ b/salt/common/tools/sbin/so-elasticsearch-indices-list @@ -18,4 +18,4 @@ . /usr/sbin/so-common -curl -s -k -L https://{{ NODEIP }}:9200/_cat/indices?pretty +{{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_cat/indices?pretty diff --git a/salt/common/tools/sbin/so-elasticsearch-indices-rw b/salt/common/tools/sbin/so-elasticsearch-indices-rw index 6b123bd0d..f5296f2b8 100755 --- a/salt/common/tools/sbin/so-elasticsearch-indices-rw +++ b/salt/common/tools/sbin/so-elasticsearch-indices-rw @@ -21,5 +21,5 @@ THEHIVEESPORT=9400 echo "Removing read only attributes for indices..." echo -curl -s -k -XPUT -H "Content-Type: application/json" -L https://$IP:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}' 2>&1 | if grep -q ack; then echo "Index settings updated..."; else echo "There was any issue updating the read-only attribute. Please ensure Elasticsearch is running.";fi; -curl -XPUT -H "Content-Type: application/json" -L http://$IP:9400/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}' 2>&1 | if grep -q ack; then echo "Index settings updated..."; else echo "There was any issue updating the read-only attribute. Please ensure Elasticsearch is running.";fi; +{{ ELASTICCURL }} -s -k -XPUT -H "Content-Type: application/json" -L https://$IP:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}' 2>&1 | if grep -q ack; then echo "Index settings updated..."; else echo "There was any issue updating the read-only attribute. Please ensure Elasticsearch is running.";fi; +{{ ELASTICCURL }} -XPUT -H "Content-Type: application/json" -L http://$IP:9400/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}' 2>&1 | if grep -q ack; then echo "Index settings updated..."; else echo "There was any issue updating the read-only attribute. Please ensure Elasticsearch is running.";fi; diff --git a/salt/common/tools/sbin/so-elasticsearch-pipeline-stats b/salt/common/tools/sbin/so-elasticsearch-pipeline-stats index 146196917..2f9edb6c1 100755 --- a/salt/common/tools/sbin/so-elasticsearch-pipeline-stats +++ b/salt/common/tools/sbin/so-elasticsearch-pipeline-stats @@ -19,7 +19,7 @@ . /usr/sbin/so-common if [ "$1" == "" ]; then - curl -s -k -L https://{{ NODEIP }}:9200/_nodes/stats | jq .nodes | jq ".[] | .ingest.pipelines" + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_nodes/stats | jq .nodes | jq ".[] | .ingest.pipelines" else - curl -s -k -L https://{{ NODEIP }}:9200/_nodes/stats | jq .nodes | jq ".[] | .ingest.pipelines.\"$1\"" + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_nodes/stats | jq .nodes | jq ".[] | .ingest.pipelines.\"$1\"" fi diff --git a/salt/common/tools/sbin/so-elasticsearch-pipeline-view b/salt/common/tools/sbin/so-elasticsearch-pipeline-view index 04901e122..9f799c07f 100755 --- a/salt/common/tools/sbin/so-elasticsearch-pipeline-view +++ b/salt/common/tools/sbin/so-elasticsearch-pipeline-view @@ -19,7 +19,7 @@ . /usr/sbin/so-common if [ "$1" == "" ]; then - curl -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/* | jq . + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/* | jq . else - curl -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/$1 | jq . + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/$1 | jq . fi diff --git a/salt/common/tools/sbin/so-elasticsearch-pipelines-list b/salt/common/tools/sbin/so-elasticsearch-pipelines-list index 565f90071..f6ef516ef 100755 --- a/salt/common/tools/sbin/so-elasticsearch-pipelines-list +++ b/salt/common/tools/sbin/so-elasticsearch-pipelines-list @@ -17,7 +17,7 @@ {%- set NODEIP = salt['pillar.get']('elasticsearch:mainip', '') -%} . /usr/sbin/so-common if [ "$1" == "" ]; then - curl -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/* | jq 'keys' + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/* | jq 'keys' else - curl -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/$1 | jq + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_ingest/pipeline/$1 | jq fi diff --git a/salt/common/tools/sbin/so-elasticsearch-shards-list b/salt/common/tools/sbin/so-elasticsearch-shards-list index 9d28ed95b..a240f993f 100755 --- a/salt/common/tools/sbin/so-elasticsearch-shards-list +++ b/salt/common/tools/sbin/so-elasticsearch-shards-list @@ -18,4 +18,4 @@ . /usr/sbin/so-common -curl -s -k -L https://{{ NODEIP }}:9200/_cat/shards?pretty +{{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_cat/shards?pretty diff --git a/salt/common/tools/sbin/so-elasticsearch-template-remove b/salt/common/tools/sbin/so-elasticsearch-template-remove index f7c3e6812..fe19a9d03 100755 --- a/salt/common/tools/sbin/so-elasticsearch-template-remove +++ b/salt/common/tools/sbin/so-elasticsearch-template-remove @@ -18,4 +18,4 @@ . /usr/sbin/so-common -curl -s -k -L -XDELETE https://{{ NODEIP }}:9200/_template/$1 +{{ ELASTICCURL }} -s -k -L -XDELETE https://{{ NODEIP }}:9200/_template/$1 diff --git a/salt/common/tools/sbin/so-elasticsearch-template-view b/salt/common/tools/sbin/so-elasticsearch-template-view index c9f3ec199..1083cb762 100755 --- a/salt/common/tools/sbin/so-elasticsearch-template-view +++ b/salt/common/tools/sbin/so-elasticsearch-template-view @@ -19,7 +19,7 @@ . /usr/sbin/so-common if [ "$1" == "" ]; then - curl -s -k -L https://{{ NODEIP }}:9200/_template/* | jq . + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_template/* | jq . else - curl -s -k -L https://{{ NODEIP }}:9200/_template/$1 | jq . + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_template/$1 | jq . fi diff --git a/salt/common/tools/sbin/so-elasticsearch-templates-list b/salt/common/tools/sbin/so-elasticsearch-templates-list index 494ca5770..6a7c4d039 100755 --- a/salt/common/tools/sbin/so-elasticsearch-templates-list +++ b/salt/common/tools/sbin/so-elasticsearch-templates-list @@ -17,7 +17,7 @@ {%- set NODEIP = salt['pillar.get']('elasticsearch:mainip', '') -%} . /usr/sbin/so-common if [ "$1" == "" ]; then - curl -s -k -L https://{{ NODEIP }}:9200/_template/* | jq 'keys' + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_template/* | jq 'keys' else - curl -s -k -L https://{{ NODEIP }}:9200/_template/$1 | jq + {{ ELASTICCURL }} -s -k -L https://{{ NODEIP }}:9200/_template/$1 | jq fi diff --git a/salt/common/tools/sbin/so-index-list b/salt/common/tools/sbin/so-index-list index cf9232150..e24599f0e 100755 --- a/salt/common/tools/sbin/so-index-list +++ b/salt/common/tools/sbin/so-index-list @@ -15,4 +15,4 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -curl -X GET -k -L "https://localhost:9200/_cat/indices?v&s=index" +{{ ELASTICCURL }} -X GET -k -L "https://localhost:9200/_cat/indices?v&s=index" diff --git a/salt/common/tools/sbin/soup b/salt/common/tools/sbin/soup index 620737c16..14e2148d0 100755 --- a/salt/common/tools/sbin/soup +++ b/salt/common/tools/sbin/soup @@ -326,7 +326,7 @@ rc1_to_rc2() { local NAME=$(echo $p | awk '{print $1}') local IP=$(echo $p | awk '{print $2}') echo "Removing the old cross cluster config for $NAME" - curl -XPUT -H 'Content-Type: application/json' http://localhost:9200/_cluster/settings -d '{"persistent":{"cluster":{"remote":{"'$NAME'":{"skip_unavailable":null,"seeds":null}}}}}' + {{ ELASTICCURL }} -XPUT -H 'Content-Type: application/json' http://localhost:9200/_cluster/settings -d '{"persistent":{"cluster":{"remote":{"'$NAME'":{"skip_unavailable":null,"seeds":null}}}}}' done Date: Mon, 24 May 2021 10:52:54 -0400 Subject: [PATCH 05/76] Switch Kratos config from argon2 to bcrypt12 --- salt/soc/files/kratos/kratos.yaml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/salt/soc/files/kratos/kratos.yaml b/salt/soc/files/kratos/kratos.yaml index c26aeec3f..a0a72b3ab 100644 --- a/salt/soc/files/kratos/kratos.yaml +++ b/salt/soc/files/kratos/kratos.yaml @@ -41,12 +41,8 @@ serve: base_url: https://{{ WEBACCESS }}/kratos/ hashers: - argon2: - parallelism: 2 - memory: 16384 - iterations: 3 - salt_length: 16 - key_length: 32 + bcrypt: + cost: 12 identity: default_schema_url: file:///kratos-conf/schema.json From 409eea677ddc6f57bc77ecbbbe6610f7b9cb5f7c Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 24 May 2021 11:50:53 -0400 Subject: [PATCH 06/76] Continue removal of argon hashing --- salt/common/init.sls | 2 -- salt/common/tools/sbin/so-user | 11 ++++------- setup/so-functions | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/salt/common/init.sls b/salt/common/init.sls index 33a8b9984..79a7c5300 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -95,7 +95,6 @@ commonpkgs: - netcat - python3-mysqldb - sqlite3 - - argon2 - libssl-dev - python3-dateutil - python3-m2crypto @@ -128,7 +127,6 @@ commonpkgs: - net-tools - curl - sqlite - - argon2 - mariadb-devel - nmap-ncat - python3 diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index b97cc8a8b..edfa4b303 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -39,10 +39,7 @@ email=$2 kratosUrl=${KRATOS_URL:-http://127.0.0.1:4434} databasePath=${KRATOS_DB_PATH:-/opt/so/conf/kratos/db/db.sqlite} -argon2Iterations=${ARGON2_ITERATIONS:-3} -argon2Memory=${ARGON2_MEMORY:-14} -argon2Parallelism=${ARGON2_PARALLELISM:-2} -argon2HashSize=${ARGON2_HASH_SIZE:-32} +bcryptRounds=${BCRYPT_ROUNDS:-12} function fail() { msg=$1 @@ -58,7 +55,7 @@ function require() { # Verify this environment is capable of running this script function verifyEnvironment() { - require "argon2" + require "htpasswd" require "jq" require "curl" require "openssl" @@ -111,8 +108,8 @@ function updatePassword() { if [[ -n $identityId ]]; then # Generate password hash - salt=$(openssl rand -hex 8) - passwordHash=$(echo "${password}" | argon2 ${salt} -id -t $argon2Iterations -m $argon2Memory -p $argon2Parallelism -l $argon2HashSize -e) + passwordHash=$(echo "${password}" | htpasswd -niBC $bcryptRounds SOUSER) | cut -c 11- + passwordHash="\$2a${passwordHash} # Update DB with new hash echo "update identity_credentials set config=CAST('{\"hashed_password\":\"${passwordHash}\"}' as BLOB) where identity_id=${identityId};" | sqlite3 "$databasePath" diff --git a/setup/so-functions b/setup/so-functions index 5ce3d6dee..33e0514fc 100755 --- a/setup/so-functions +++ b/setup/so-functions @@ -2079,7 +2079,7 @@ saltify() { 'MANAGER' | 'EVAL' | 'MANAGERSEARCH' | 'FLEET' | 'HELIXSENSOR' | 'STANDALONE'| 'IMPORT') reserve_group_ids >> "$setup_log" 2>&1 if [[ ! $is_iso ]]; then - logCmd "yum -y install sqlite argon2 curl mariadb-devel" + logCmd "yum -y install sqlite curl mariadb-devel" fi # Download Ubuntu Keys in case manager updates = 1 mkdir -p /opt/so/gpg >> "$setup_log" 2>&1 @@ -2175,7 +2175,7 @@ saltify() { retry 50 10 "apt-get update" >> "$setup_log" 2>&1 || exit 1 set_progress_str 6 'Installing various dependencies' - retry 50 10 "apt-get -y install sqlite3 argon2 libssl-dev" >> "$setup_log" 2>&1 || exit 1 + retry 50 10 "apt-get -y install sqlite3 libssl-dev" >> "$setup_log" 2>&1 || exit 1 set_progress_str 7 'Installing salt-master' retry 50 10 "apt-get -y install salt-master=3003+ds-1" >> "$setup_log" 2>&1 || exit 1 retry 50 10 "apt-mark hold salt-master" >> "$setup_log" 2>&1 || exit 1 From a4226cc39a72d26f58d84d9199c5c331b049f526 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 24 May 2021 15:14:05 -0400 Subject: [PATCH 07/76] use elastic map file --- salt/common/init.sls | 9 ++------- .../tools/sbin/so-elasticsearch-templates-load | 4 ++-- .../files/bin/so-curator-closed-delete-delete | 6 +++--- salt/curator/init.sls | 5 ++++- salt/elasticsearch/auth.map.jinja | 7 +++++++ .../files/so-elasticsearch-pipelines | 6 +++--- salt/utility/init.sls | 15 +++------------ 7 files changed, 24 insertions(+), 28 deletions(-) create mode 100644 salt/elasticsearch/auth.map.jinja diff --git a/salt/common/init.sls b/salt/common/init.sls index 948adee99..389b0b8a3 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -2,8 +2,7 @@ {% if sls in allowed_states %} {% set role = grains.id.split('_') | last %} -{% set ELASTICUSER = salt['pillar.get']('elasticsearch:auth:user', '' ) %} -{% set ELASTICPASS = salt['pillar.get']('elasticsearch:auth:pass', '' ) %} +{% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} # Remove variables.txt from /tmp - This is temp rmvariablesfile: @@ -181,11 +180,7 @@ utilsyncscripts: - template: jinja - source: salt://common/tools/sbin - defaults: - ELASTICCURL: "curl" -{% if salt['pillar.get']('elasticsearch:auth_enabled', False) %} - - context: - ELASTICCURL: "curl --user {{ELASTICUSER}}:{{ELASTICPASS}}" -{% endif %} + ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} {% if role in ['eval', 'standalone', 'sensor', 'heavynode'] %} diff --git a/salt/common/tools/sbin/so-elasticsearch-templates-load b/salt/common/tools/sbin/so-elasticsearch-templates-load index 42a836854..30ab66b48 100755 --- a/salt/common/tools/sbin/so-elasticsearch-templates-load +++ b/salt/common/tools/sbin/so-elasticsearch-templates-load @@ -30,7 +30,7 @@ echo -n "Waiting for ElasticSearch..." COUNT=0 ELASTICSEARCH_CONNECTED="no" while [[ "$COUNT" -le 240 ]]; do - curl -k --output /dev/null --silent --head --fail -L https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" + {{ ELASTICCURL }} -k --output /dev/null --silent --head --fail -L https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" if [ $? -eq 0 ]; then ELASTICSEARCH_CONNECTED="yes" echo "connected!" @@ -51,7 +51,7 @@ cd ${ELASTICSEARCH_TEMPLATES} echo "Loading templates..." -for i in *; do TEMPLATE=$(echo $i | cut -d '-' -f2); echo "so-$TEMPLATE"; curl -k ${ELASTICSEARCH_AUTH} -s -XPUT -L https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/_template/so-$TEMPLATE -H 'Content-Type: application/json' -d@$i 2>/dev/null; echo; done +for i in *; do TEMPLATE=$(echo $i | cut -d '-' -f2); echo "so-$TEMPLATE"; {{ ELASTICCURL }} -k ${ELASTICSEARCH_AUTH} -s -XPUT -L https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/_template/so-$TEMPLATE -H 'Content-Type: application/json' -d@$i 2>/dev/null; echo; done echo cd - >/dev/null diff --git a/salt/curator/files/bin/so-curator-closed-delete-delete b/salt/curator/files/bin/so-curator-closed-delete-delete index 9cc94833c..7dd7b82e7 100755 --- a/salt/curator/files/bin/so-curator-closed-delete-delete +++ b/salt/curator/files/bin/so-curator-closed-delete-delete @@ -34,7 +34,7 @@ overlimit() { closedindices() { - INDICES=$(curl -s -k https://{{ELASTICSEARCH_HOST}}:{{ELASTICSEARCH_PORT}}/_cat/indices?h=index\&expand_wildcards=closed 2> /dev/null) + INDICES=$({{ ELASTICCURL }} -s -k https://{{ELASTICSEARCH_HOST}}:{{ELASTICSEARCH_PORT}}/_cat/indices?h=index\&expand_wildcards=closed 2> /dev/null) [ $? -eq 1 ] && return false echo ${INDICES} | grep -q -E "(logstash-|so-)" } @@ -49,10 +49,10 @@ while overlimit && closedindices; do # First, get the list of closed indices using _cat/indices?h=index\&expand_wildcards=closed. # Then, sort by date by telling sort to use hyphen as delimiter and then sort on the third field. # Finally, select the first entry in that sorted list. - OLDEST_INDEX=$(curl -s -k https://{{ELASTICSEARCH_HOST}}:{{ELASTICSEARCH_PORT}}/_cat/indices?h=index\&expand_wildcards=closed | grep -E "(logstash-|so-)" | sort -t- -k3 | head -1) + OLDEST_INDEX=$({{ ELASTICCURL }} -s -k https://{{ELASTICSEARCH_HOST}}:{{ELASTICSEARCH_PORT}}/_cat/indices?h=index\&expand_wildcards=closed | grep -E "(logstash-|so-)" | sort -t- -k3 | head -1) # Now that we've determined OLDEST_INDEX, ask Elasticsearch to delete it. - curl -XDELETE -k https://{{ELASTICSEARCH_HOST}}:{{ELASTICSEARCH_PORT}}/${OLDEST_INDEX} + {{ ELASTICCURL }} -XDELETE -k https://{{ELASTICSEARCH_HOST}}:{{ELASTICSEARCH_PORT}}/${OLDEST_INDEX} # Finally, write a log entry that says we deleted it. echo "$(date) - Used disk space exceeds LOG_SIZE_LIMIT ({{LOG_SIZE_LIMIT}} GB) - Index ${OLDEST_INDEX} deleted ..." >> ${LOG} diff --git a/salt/curator/init.sls b/salt/curator/init.sls index 245b700d0..966b0b857 100644 --- a/salt/curator/init.sls +++ b/salt/curator/init.sls @@ -5,6 +5,7 @@ {% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %} {% set MANAGER = salt['grains.get']('master') %} {% if grains['role'] in ['so-eval', 'so-node', 'so-managersearch', 'so-heavynode', 'so-standalone'] %} + {% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} # Curator # Create the group curatorgroup: @@ -66,6 +67,8 @@ curcloseddeldel: - group: 939 - mode: 755 - template: jinja + - defaults: + ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} curclose: file.managed: @@ -147,4 +150,4 @@ append_so-curator_so-status.conf: test.fail_without_changes: - name: {{sls}}_state_not_allowed -{% endif %} \ No newline at end of file +{% endif %} diff --git a/salt/elasticsearch/auth.map.jinja b/salt/elasticsearch/auth.map.jinja new file mode 100644 index 000000000..af13729ef --- /dev/null +++ b/salt/elasticsearch/auth.map.jinja @@ -0,0 +1,7 @@ +{% set ELASTICAUTH = salt['pillar.filter_by']({ + True: { + 'user': salt['pillar.get']('elasticsearch:auth:user'), + 'pass': salt['pillar.get']('elasticsearch:auth:pass'), + 'elasticcurl':'curl --user {{ELASTICAUTH.user}}:{{ELASTICAUTH.pass}}'}, + False: {'elasticcurl': 'curl'}, +}, pillar='elasticsearch:auth:enabled') %} diff --git a/salt/elasticsearch/files/so-elasticsearch-pipelines b/salt/elasticsearch/files/so-elasticsearch-pipelines index fca50b7d4..5d103963e 100755 --- a/salt/elasticsearch/files/so-elasticsearch-pipelines +++ b/salt/elasticsearch/files/so-elasticsearch-pipelines @@ -27,7 +27,7 @@ echo -n "Waiting for ElasticSearch..." COUNT=0 ELASTICSEARCH_CONNECTED="no" while [[ "$COUNT" -le 240 ]]; do - curl ${ELASTICSEARCH_AUTH} -k --output /dev/null --silent --head --fail -L https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" + {{ ELASTICCURL }} -k --output /dev/null --silent --head --fail -L https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" if [ $? -eq 0 ]; then ELASTICSEARCH_CONNECTED="yes" echo "connected!" @@ -47,9 +47,9 @@ fi cd ${ELASTICSEARCH_INGEST_PIPELINES} echo "Loading pipelines..." -for i in *; do echo $i; RESPONSE=$(curl ${ELASTICSEARCH_AUTH} -k -XPUT -L https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/_ingest/pipeline/$i -H 'Content-Type: application/json' -d@$i 2>/dev/null); echo $RESPONSE; if [[ "$RESPONSE" == *"error"* ]]; then RETURN_CODE=1; fi; done +for i in *; do echo $i; RESPONSE=$({{ ELASTICCURL }} -k -XPUT -L https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/_ingest/pipeline/$i -H 'Content-Type: application/json' -d@$i 2>/dev/null); echo $RESPONSE; if [[ "$RESPONSE" == *"error"* ]]; then RETURN_CODE=1; fi; done echo cd - >/dev/null -exit $RETURN_CODE \ No newline at end of file +exit $RETURN_CODE diff --git a/salt/utility/init.sls b/salt/utility/init.sls index 5558139de..0b4f0f2c3 100644 --- a/salt/utility/init.sls +++ b/salt/utility/init.sls @@ -1,8 +1,7 @@ {% from 'allowed_states.map.jinja' import allowed_states %} {% if sls in allowed_states %} - {% set ELASTICUSER = salt['pillar.get']('elasticsearch:auth:user', '' ) %} - {% set ELASTICPASS = salt['pillar.get']('elasticsearch:auth:pass', '' ) %} + {% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} # This state is for checking things {% if grains['role'] in ['so-manager', 'so-managersearch', 'so-standalone'] %} @@ -15,11 +14,7 @@ crossclusterson: - source: salt://utility/bin/crossthestreams - template: jinja - defaults: - ELASTICCURL: "curl" - {% if salt['pillar.get']('elasticsearch:auth_enabled', False) %} - - context: - ELASTICCURL: "curl --user {{ELASTICUSER}}:{{ELASTICPASS}}" - {% endif %} + ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} {% endif %} {% if grains['role'] in ['so-eval', 'so-import'] %} @@ -31,11 +26,7 @@ fixsearch: - source: salt://utility/bin/eval - template: jinja - defaults: - ELASTICCURL: "curl" - {% if salt['pillar.get']('elasticsearch:auth_enabled', False) %} - - context: - ELASTICCURL: "curl --user {{ELASTICUSER}}:{{ELASTICPASS}}" - {% endif %} + ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} {% endif %} {% else %} From ba3a51387caeb293c2fbbc134931a18e70b885d8 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 24 May 2021 15:31:46 -0400 Subject: [PATCH 08/76] set default to False --- salt/elasticsearch/auth.map.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/elasticsearch/auth.map.jinja b/salt/elasticsearch/auth.map.jinja index af13729ef..f216ef3c2 100644 --- a/salt/elasticsearch/auth.map.jinja +++ b/salt/elasticsearch/auth.map.jinja @@ -4,4 +4,4 @@ 'pass': salt['pillar.get']('elasticsearch:auth:pass'), 'elasticcurl':'curl --user {{ELASTICAUTH.user}}:{{ELASTICAUTH.pass}}'}, False: {'elasticcurl': 'curl'}, -}, pillar='elasticsearch:auth:enabled') %} +}, pillar='elasticsearch:auth:enabled', default=False) %} From 87609ba5d1afab1179e6e15105f4ade629d8d34a Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 24 May 2021 15:44:01 -0400 Subject: [PATCH 09/76] fix elasticcurl if auth is enabled --- salt/elasticsearch/auth.map.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/elasticsearch/auth.map.jinja b/salt/elasticsearch/auth.map.jinja index f216ef3c2..147b0157b 100644 --- a/salt/elasticsearch/auth.map.jinja +++ b/salt/elasticsearch/auth.map.jinja @@ -2,6 +2,6 @@ True: { 'user': salt['pillar.get']('elasticsearch:auth:user'), 'pass': salt['pillar.get']('elasticsearch:auth:pass'), - 'elasticcurl':'curl --user {{ELASTICAUTH.user}}:{{ELASTICAUTH.pass}}'}, + 'elasticcurl':'curl --user ' ~ salt['pillar.get']('elasticsearch:auth:user') ~ ':' ~ salt['pillar.get']('elasticsearch:auth:pass') }, False: {'elasticcurl': 'curl'}, }, pillar='elasticsearch:auth:enabled', default=False) %} From 8c6489a49a945ee08c2906bd9955bc858bbb489b Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 24 May 2021 15:48:05 -0400 Subject: [PATCH 10/76] Initial pass at synchronizing users file --- salt/common/tools/sbin/so-user | 21 ++++++++++++++++++--- salt/elasticsearch/init.sls | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index edfa4b303..dbd755bc4 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -40,6 +40,7 @@ email=$2 kratosUrl=${KRATOS_URL:-http://127.0.0.1:4434} databasePath=${KRATOS_DB_PATH:-/opt/so/conf/kratos/db/db.sqlite} bcryptRounds=${BCRYPT_ROUNDS:-12} +extractedHashFile=${EXTRACTED_HASH_FILE:-/opt/so/conf/elasticsearch/users} function fail() { msg=$1 @@ -108,15 +109,19 @@ function updatePassword() { if [[ -n $identityId ]]; then # Generate password hash - passwordHash=$(echo "${password}" | htpasswd -niBC $bcryptRounds SOUSER) | cut -c 11- - passwordHash="\$2a${passwordHash} - + passwordHash=$(echo "${password}" | htpasswd -niBC $bcryptRounds SOUSER) + passwordHash=$(echo "$passwordHash" | cut -c 11-) + passwordHash="\$2a${passwordHash}" # Update DB with new hash echo "update identity_credentials set config=CAST('{\"hashed_password\":\"${passwordHash}\"}' as BLOB) where identity_id=${identityId};" | sqlite3 "$databasePath" [[ $? != 0 ]] && fail "Unable to update password" fi } +function extractHashes() { + echo "select ici.identifier || ':' || json_extract(ic.config, '$.hashed_password') from identity_credential_identifiers ici, identity_credentials ic where ici.identity_credential_id=ic.id and json_extract(ic.config, '$.hashed_password') is not null order by ici.identifier" | sqlite3 "$databasePath" > "$extractedHashFile" +} + function listUsers() { response=$(curl -Ss -L ${kratosUrl}/identities) [[ $? != 0 ]] && fail "Unable to communicate with Kratos" @@ -208,6 +213,7 @@ case "${operation}" in validateEmail "$email" updatePassword createUser "$email" + extractHashes echo "Successfully added new user to SOC" check_container thehive && echo $password | so-thehive-user-add "$email" check_container fleet && echo $password | so-fleet-user-add "$email" @@ -223,6 +229,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateUser "$email" + extractHashes echo "Successfully updated user" ;; @@ -231,6 +238,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'active' + extractHashes echo "Successfully enabled user" check_container thehive && so-thehive-user-enable "$email" true check_container fleet && so-fleet-user-enable "$email" true @@ -241,6 +249,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'locked' + extractHashes echo "Successfully disabled user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false @@ -251,11 +260,17 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" deleteUser "$email" + extractHashes echo "Successfully deleted user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false ;; + "sync") + extractHashes + echo "Synchronization complete" + ;; + "validate") validateEmail "$email" updatePassword diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index df297986a..c6ac600ef 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -202,6 +202,8 @@ so-elasticsearch: - binds: - /opt/so/conf/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - /opt/so/conf/elasticsearch/log4j2.properties:/usr/share/elasticsearch/config/log4j2.properties:ro + - /opt/so/conf/elasticsearch/users:/usr/share/elasticsearch/config/users:ro + - /opt/so/conf/elasticsearch/users_roles:/usr/share/elasticsearch/config/users_roles:ro - /nsm/elasticsearch:/usr/share/elasticsearch/data:rw - /opt/so/log/elasticsearch:/var/log/elasticsearch:rw - /opt/so/conf/ca/cacerts:/etc/pki/ca-trust/extracted/java/cacerts:ro From 2deb703272761598aba2557f05c132244c4989c3 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 24 May 2021 16:30:55 -0400 Subject: [PATCH 11/76] map users_roles and users conf into docker container --- salt/elasticsearch/init.sls | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index df297986a..7e0e700e9 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -35,6 +35,7 @@ {% endif %} {% set TEMPLATES = salt['pillar.get']('elasticsearch:templates', {}) %} +{% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} vm.max_map_count: sysctl.present: @@ -213,6 +214,10 @@ so-elasticsearch: - /etc/pki/elasticsearch.crt:/usr/share/elasticsearch/config/elasticsearch.crt:ro - /etc/pki/elasticsearch.key:/usr/share/elasticsearch/config/elasticsearch.key:ro - /etc/pki/elasticsearch.p12:/usr/share/elasticsearch/config/elasticsearch.p12:ro + {% if salt['pillar.get']('elasticsearch:auth:enabled', False) %} + - /opt/so/conf/elasticsearch/users_roles:/usr/share/elasticsearch/config/users_roles:ro + - /opt/so/conf/elasticsearch/users:/usr/share/elasticsearch/config/users:ro + {% endif %} - watch: - file: cacertz - file: esyml From bd301880ade0360deef8cf9362a9a598533a63aa Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Mon, 24 May 2021 16:32:30 -0400 Subject: [PATCH 12/76] define the default --- salt/elasticsearch/init.sls | 2 ++ 1 file changed, 2 insertions(+) diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 7e0e700e9..0a3ea0719 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -237,6 +237,8 @@ so-elasticsearch-pipelines-file: - group: 939 - mode: 754 - template: jinja + - defaults: + ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} so-elasticsearch-pipelines: cmd.run: From 5a1e8d9fe96d2d553490d41a882f0e6b4949873e Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 08:50:55 -0400 Subject: [PATCH 13/76] update kibana scripts for elastic auth --- salt/common/tools/sbin/so-common | 3 ++- salt/common/tools/sbin/so-kibana-space-defaults | 8 ++++---- salt/kibana/bin/so-kibana-config-load | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/salt/common/tools/sbin/so-common b/salt/common/tools/sbin/so-common index 22c7543ea..21948e67d 100755 --- a/salt/common/tools/sbin/so-common +++ b/salt/common/tools/sbin/so-common @@ -486,12 +486,13 @@ wait_for_web_response() { url=$1 expected=$2 maxAttempts=${3:-300} + curlcmd=${4:-curl} logfile=/root/wait_for_web_response.log attempt=0 while [[ $attempt -lt $maxAttempts ]]; do attempt=$((attempt+1)) echo "Waiting for value '$expected' at '$url' ($attempt/$maxAttempts)" - result=$(curl -ks -L $url) + result=$($curlcmd -ks -L $url) exitcode=$? echo "--------------------------------------------------" >> $logfile diff --git a/salt/common/tools/sbin/so-kibana-space-defaults b/salt/common/tools/sbin/so-kibana-space-defaults index edf356d45..48225e2f4 100755 --- a/salt/common/tools/sbin/so-kibana-space-defaults +++ b/salt/common/tools/sbin/so-kibana-space-defaults @@ -1,13 +1,13 @@ . /usr/sbin/so-common -wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" +wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}" ## This hackery will be removed if using Elastic Auth ## # Let's snag a cookie from Kibana -THECOOKIE=$(curl -c - -X GET http://localhost:5601/ | grep sid | awk '{print $7}') +THECOOKIE=$({{ ELASTICCURL }} -c - -X GET http://localhost:5601/ | grep sid | awk '{print $7}') # Disable certain Features from showing up in the Kibana UI echo echo "Setting up default Space:" -curl -b "sid=$THECOOKIE" -L -X PUT "localhost:5601/api/spaces/space/default" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d' {"id":"default","name":"Default","disabledFeatures":["ml","enterpriseSearch","siem","logs","infrastructure","apm","uptime","monitoring","stackAlerts","actions","fleet"]} ' >> /opt/so/log/kibana/misc.log -echo \ No newline at end of file +{{ ELASTICCURL }} -b "sid=$THECOOKIE" -L -X PUT "localhost:5601/api/spaces/space/default" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d' {"id":"default","name":"Default","disabledFeatures":["ml","enterpriseSearch","siem","logs","infrastructure","apm","uptime","monitoring","stackAlerts","actions","fleet"]} ' >> /opt/so/log/kibana/misc.log +echo diff --git a/salt/kibana/bin/so-kibana-config-load b/salt/kibana/bin/so-kibana-config-load index f07377018..d0e6f1edb 100644 --- a/salt/kibana/bin/so-kibana-config-load +++ b/salt/kibana/bin/so-kibana-config-load @@ -16,11 +16,11 @@ cp /opt/so/conf/kibana/saved_objects.ndjson.template /opt/so/conf/kibana/saved_o # SOCtopus and Manager sed -i "s/PLACEHOLDER/{{ MANAGER }}/g" /opt/so/conf/kibana/saved_objects.ndjson -wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" +wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}"" ## This hackery will be removed if using Elastic Auth ## # Let's snag a cookie from Kibana -THECOOKIE=$(curl -c - -X GET http://localhost:5601/ | grep sid | awk '{print $7}') +THECOOKIE=$({{ ELASTICCURL }} -c - -X GET http://localhost:5601/ | grep sid | awk '{print $7}') # Load saved objects -curl -b "sid=$THECOOKIE" -L -X POST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "kbn-xsrf: true" --form file=@/opt/so/conf/kibana/saved_objects.ndjson >> /opt/so/log/kibana/misc.log \ No newline at end of file +{{ ELASTICCURL }} -b "sid=$THECOOKIE" -L -X POST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "kbn-xsrf: true" --form file=@/opt/so/conf/kibana/saved_objects.ndjson >> /opt/so/log/kibana/misc.log From 8d9d5a267ac7c3f34bd0e482f5a107c06161cc64 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 11:52:58 -0400 Subject: [PATCH 14/76] generate elasticsearch.auth pillar if it doesnt exist --- pillar/top.sls | 5 ++++- salt/elasticsearch/auth.sls | 9 +++++++++ salt/elasticsearch/files/curl.config | 1 + salt/elasticsearch/init.sls | 8 ++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 salt/elasticsearch/auth.sls create mode 100644 salt/elasticsearch/files/curl.config diff --git a/pillar/top.sls b/pillar/top.sls index a795e03c1..80e02902e 100644 --- a/pillar/top.sls +++ b/pillar/top.sls @@ -46,6 +46,9 @@ base: - logstash.manager - logstash.search - elasticsearch.search +{% if salt['file.exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} + - elasticsearch.auth +{% endif %} - data.* - zeeklogs - secrets @@ -89,4 +92,4 @@ base: - secrets - elasticsearch.eval - global - - minions.{{ grains.id }} \ No newline at end of file + - minions.{{ grains.id }} diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls new file mode 100644 index 000000000..a51abca1c --- /dev/null +++ b/salt/elasticsearch/auth.sls @@ -0,0 +1,9 @@ +elastic_auth_pillar: + file.managed: + - name: /opt/so/saltstack/local/pillar/elasticsearch/auth.sls + - contents: | + elasticsearch: + auth: + enabled: False + user: so_elastic + pass: {{ salt['random.get_str'](20) }} diff --git a/salt/elasticsearch/files/curl.config b/salt/elasticsearch/files/curl.config new file mode 100644 index 000000000..e4633df6c --- /dev/null +++ b/salt/elasticsearch/files/curl.config @@ -0,0 +1 @@ +user = "salt['pillar.get']('elasticsearch:auth:user'):salt['pillar.get']('elasticsearch:auth:pass')" diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 0a3ea0719..f0eee6d44 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -256,6 +256,14 @@ so-elasticsearch-templates: - template: jinja {% endif %} +elastic_curl_config: + file.managed: + - name: /opt/so/conf/elasticsearch/curl.config + - mode: 600 + # since we are generating a random password, and we don't want that to happen everytime + # a highstate runs, we only manage the file if it doesn't exist + - unless: ls /opt/so/conf/elasticsearch/curl.config + {% endif %} {# if grains['role'] != 'so-helix' #} {% else %} From 6da0b57ce1960858da182cc49c4a4d4eaa6ca706 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 11:55:22 -0400 Subject: [PATCH 15/76] fix file.file_exists --- pillar/top.sls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pillar/top.sls b/pillar/top.sls index 80e02902e..8bd67c174 100644 --- a/pillar/top.sls +++ b/pillar/top.sls @@ -46,7 +46,7 @@ base: - logstash.manager - logstash.search - elasticsearch.search -{% if salt['file.exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} +{% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} - elasticsearch.auth {% endif %} - data.* From 58ec31d6c7c3cb9cacd76e907aaf59736814cabc Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 12:02:41 -0400 Subject: [PATCH 16/76] pass ELASTICAUTH to script --- salt/kibana/init.sls | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/salt/kibana/init.sls b/salt/kibana/init.sls index 75b96b72a..61498cfeb 100644 --- a/salt/kibana/init.sls +++ b/salt/kibana/init.sls @@ -4,6 +4,7 @@ {% set VERSION = salt['pillar.get']('global:soversion', 'HH1.2.2') %} {% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %} {% set MANAGER = salt['grains.get']('master') %} +{% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} # Add ES Group kibanasearchgroup: @@ -63,6 +64,8 @@ kibanabin: - source: salt://kibana/bin/so-kibana-config-load - mode: 755 - template: jinja + - defaults: + ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} # Start the kibana docker so-kibana: @@ -113,4 +116,4 @@ so-kibana-config-load: test.fail_without_changes: - name: {{sls}}_state_not_allowed -{% endif %} \ No newline at end of file +{% endif %} From 35cc7b27e9f66716621ae9c33a0a9045acba934c Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 13:12:30 -0400 Subject: [PATCH 17/76] remove extra quote --- salt/kibana/bin/so-kibana-config-load | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/kibana/bin/so-kibana-config-load b/salt/kibana/bin/so-kibana-config-load index d0e6f1edb..58535a886 100644 --- a/salt/kibana/bin/so-kibana-config-load +++ b/salt/kibana/bin/so-kibana-config-load @@ -16,7 +16,7 @@ cp /opt/so/conf/kibana/saved_objects.ndjson.template /opt/so/conf/kibana/saved_o # SOCtopus and Manager sed -i "s/PLACEHOLDER/{{ MANAGER }}/g" /opt/so/conf/kibana/saved_objects.ndjson -wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}"" +wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}" ## This hackery will be removed if using Elastic Auth ## # Let's snag a cookie from Kibana From 747dc77c92032d0a569e80706d65d3731ef49b77 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 13:23:26 -0400 Subject: [PATCH 18/76] comment out the hackery --- salt/kibana/bin/so-kibana-config-load | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/kibana/bin/so-kibana-config-load b/salt/kibana/bin/so-kibana-config-load index 58535a886..8f80b5c3d 100644 --- a/salt/kibana/bin/so-kibana-config-load +++ b/salt/kibana/bin/so-kibana-config-load @@ -16,7 +16,7 @@ cp /opt/so/conf/kibana/saved_objects.ndjson.template /opt/so/conf/kibana/saved_o # SOCtopus and Manager sed -i "s/PLACEHOLDER/{{ MANAGER }}/g" /opt/so/conf/kibana/saved_objects.ndjson -wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}" +#wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}" ## This hackery will be removed if using Elastic Auth ## # Let's snag a cookie from Kibana From e261c197f3aacc639ca4583e343a1a6daafc6dab Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 13:46:18 -0400 Subject: [PATCH 19/76] add elasticsearch.auth state to statnalone node --- salt/elasticsearch/auth.sls | 3 +++ salt/elasticsearch/init.sls | 3 --- salt/top.sls | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls index a51abca1c..e8ab1e378 100644 --- a/salt/elasticsearch/auth.sls +++ b/salt/elasticsearch/auth.sls @@ -7,3 +7,6 @@ elastic_auth_pillar: enabled: False user: so_elastic pass: {{ salt['random.get_str'](20) }} + # since we are generating a random password, and we don't want that to happen everytime + # a highstate runs, we only manage the file if it doesn't exist + - unless: ls /opt/so/saltstack/local/pillar/elasticsearch/auth.sls diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index f0eee6d44..7005a66c5 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -260,9 +260,6 @@ elastic_curl_config: file.managed: - name: /opt/so/conf/elasticsearch/curl.config - mode: 600 - # since we are generating a random password, and we don't want that to happen everytime - # a highstate runs, we only manage the file if it doesn't exist - - unless: ls /opt/so/conf/elasticsearch/curl.config {% endif %} {# if grains['role'] != 'so-helix' #} diff --git a/salt/top.sls b/salt/top.sls index 8a12aaa26..f3f2958ae 100644 --- a/salt/top.sls +++ b/salt/top.sls @@ -238,6 +238,7 @@ base: {%- endif %} {%- if ELASTICSEARCH %} - elasticsearch + - elasticsearch.auth {%- endif %} {%- if LOGSTASH %} - logstash From c3b2e1e8b22d65d05f5a0e87a615ef28af1530c8 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 25 May 2021 16:16:57 -0400 Subject: [PATCH 20/76] dont show changes --- salt/elasticsearch/init.sls | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 7005a66c5..65a3d2bca 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -260,6 +260,7 @@ elastic_curl_config: file.managed: - name: /opt/so/conf/elasticsearch/curl.config - mode: 600 + - show_changes: False {% endif %} {# if grains['role'] != 'so-helix' #} From ec2f8fe6c88527d0a4b1cc322b17115c930ba69d Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Tue, 25 May 2021 17:16:05 -0400 Subject: [PATCH 21/76] Synchronize SOC passwords with Elastic --- salt/common/tools/sbin/so-user | 74 ++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index dbd755bc4..b516cf6ad 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -40,7 +40,8 @@ email=$2 kratosUrl=${KRATOS_URL:-http://127.0.0.1:4434} databasePath=${KRATOS_DB_PATH:-/opt/so/conf/kratos/db/db.sqlite} bcryptRounds=${BCRYPT_ROUNDS:-12} -extractedHashFile=${EXTRACTED_HASH_FILE:-/opt/so/conf/elasticsearch/users} +elasticUsersFile=${ELASTIC_USERS_FILE:-/opt/so/conf/elasticsearch/users} +elasticRolesFile=${ELASTIC_ROLES_FILE:-/opt/so/conf/elasticsearch/users_roles} function fail() { msg=$1 @@ -93,6 +94,16 @@ function validateEmail() { fi } +function hashPassword() { + password=$1 + + passwordHash=$(echo "${password}" | htpasswd -niBC $bcryptRounds SOUSER) + passwordHash=$(echo "$passwordHash" | cut -c 11-) + passwordHash="\$2a${passwordHash}" # still waiting for https://github.com/elastic/elasticsearch/issues/51132 + echo "$passwordHash" +} + + function updatePassword() { identityId=$1 @@ -109,17 +120,54 @@ function updatePassword() { if [[ -n $identityId ]]; then # Generate password hash - passwordHash=$(echo "${password}" | htpasswd -niBC $bcryptRounds SOUSER) - passwordHash=$(echo "$passwordHash" | cut -c 11-) - passwordHash="\$2a${passwordHash}" + passwordHash=$(hashPassword "$password") # Update DB with new hash - echo "update identity_credentials set config=CAST('{\"hashed_password\":\"${passwordHash}\"}' as BLOB) where identity_id=${identityId};" | sqlite3 "$databasePath" + echo "update identity_credentials set config=CAST('{\"hashed_password\":\"$passwordHash\"}' as BLOB) where identity_id=${identityId};" | sqlite3 "$databasePath" [[ $? != 0 ]] && fail "Unable to update password" fi } -function extractHashes() { - echo "select ici.identifier || ':' || json_extract(ic.config, '$.hashed_password') from identity_credential_identifiers ici, identity_credentials ic where ici.identity_credential_id=ic.id and json_extract(ic.config, '$.hashed_password') is not null order by ici.identifier" | sqlite3 "$databasePath" > "$extractedHashFile" +function createElasticTmpFile() { + filename=$1 + tmpFile=${filename}.tmp + truncate -s 0 "$tmpFile" + chmod 600 "$tmpFile" + chown elasticsearch:elasticsearch "$tmpFile" + echo "$tmpFile" +} + +function syncElastic() { + usersFileTmp=$(createElasticTmpFile "${elasticUsersFile}") + rolesFileTmp=$(createElasticTmpFile "${elasticRolesFile}") + + sysUser=$(lookup_pillar "auth:user" "elasticsearch") + sysPass=$(lookup_pillar "auth:pass" "elasticsearch") + sysHash=$(hashPassword "$sysPass") + + # Generate the new users file + echo "${sysUser}:${sysHash}" >> "$usersFileTmp" + echo "select '{\"user\":\"' || ici.identifier || '\", \"data\":' || ic.config || '}'" \ + "from identity_credential_identifiers ici, identity_credentials ic " \ + "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ + "order by ici.identifier;" | \ + sqlite3 "$databasePath" | \ + jq -r '.user + ":" + .data.hashed_password' \ + >> "$usersFileTmp" + mv -f "$usersFileTmp" "$elasticUsersFile" + + # Generate the new users_roles file + echo "superuser:${sysUser}" >> "$rolesFileTmp" + echo "select 'superuser:' || ici.identifier " \ + "from identity_credential_identifiers ici, identity_credentials ic " \ + "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ + "order by ici.identifier;" | \ + sqlite3 "$databasePath" \ + >> "$rolesFileTmp" + mv -f "$rolesFileTmp" "$elasticRolesFile" +} + +function syncAll() { + syncElastic } function listUsers() { @@ -213,7 +261,7 @@ case "${operation}" in validateEmail "$email" updatePassword createUser "$email" - extractHashes + syncAll echo "Successfully added new user to SOC" check_container thehive && echo $password | so-thehive-user-add "$email" check_container fleet && echo $password | so-fleet-user-add "$email" @@ -229,7 +277,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateUser "$email" - extractHashes + syncAll echo "Successfully updated user" ;; @@ -238,7 +286,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'active' - extractHashes + syncAll echo "Successfully enabled user" check_container thehive && so-thehive-user-enable "$email" true check_container fleet && so-fleet-user-enable "$email" true @@ -249,7 +297,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'locked' - extractHashes + syncAll echo "Successfully disabled user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false @@ -260,14 +308,14 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" deleteUser "$email" - extractHashes + syncAll echo "Successfully deleted user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false ;; "sync") - extractHashes + syncAll echo "Synchronization complete" ;; From a6a4c03029567d8d008e82c60dbb44f2fb6d9049 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 26 May 2021 12:08:10 -0400 Subject: [PATCH 22/76] Improve error scenarios for user sync; Ensure user sync runs before Elastic container starts --- salt/common/tools/sbin/so-user | 5 +++++ salt/elasticsearch/init.sls | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index b516cf6ad..7362c94a2 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -142,6 +142,7 @@ function syncElastic() { sysUser=$(lookup_pillar "auth:user" "elasticsearch") sysPass=$(lookup_pillar "auth:pass" "elasticsearch") + [[ -z "$sysUser" || -z "$sysPass" ]] && fail "Elastic auth credentials for system user are missing" sysHash=$(hashPassword "$sysPass") # Generate the new users file @@ -153,7 +154,9 @@ function syncElastic() { sqlite3 "$databasePath" | \ jq -r '.user + ":" + .data.hashed_password' \ >> "$usersFileTmp" + [[ $? != 0 ]] && fail "Unable to read credential hashes from database" mv -f "$usersFileTmp" "$elasticUsersFile" + [[ $? != 0 ]] && fail "Unable to create users file: $elasticUsersFile" # Generate the new users_roles file echo "superuser:${sysUser}" >> "$rolesFileTmp" @@ -163,7 +166,9 @@ function syncElastic() { "order by ici.identifier;" | \ sqlite3 "$databasePath" \ >> "$rolesFileTmp" + [[ $? != 0 ]] && fail "Unable to read credential IDs from database" mv -f "$rolesFileTmp" "$elasticRolesFile" + [[ $? != 0 ]] && fail "Unable to create users file: $elasticRolesFile" } function syncAll() { diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index c6ac600ef..dd4af7696 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -169,6 +169,14 @@ eslogdir: - group: 939 - makedirs: True +# Must run before elasticsearch docker container is started! +syncesusers: + cmd.run: + - name: so-user sync + - creates: + - /opt/so/conf/elasticsearch/users + - /opt/so/conf/elasticsearch/users_roles + so-elasticsearch: docker_container.running: - image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-elasticsearch:{{ VERSION }} From c531ef0773df174d92dd2ce2ae5b9504442749bd Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 26 May 2021 13:44:30 -0400 Subject: [PATCH 23/76] Move user sync'd files to saltstack for grid propagation --- salt/common/tools/sbin/so-user | 4 ++-- salt/elasticsearch/init.sls | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 7362c94a2..23034a6e9 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -40,8 +40,8 @@ email=$2 kratosUrl=${KRATOS_URL:-http://127.0.0.1:4434} databasePath=${KRATOS_DB_PATH:-/opt/so/conf/kratos/db/db.sqlite} bcryptRounds=${BCRYPT_ROUNDS:-12} -elasticUsersFile=${ELASTIC_USERS_FILE:-/opt/so/conf/elasticsearch/users} -elasticRolesFile=${ELASTIC_ROLES_FILE:-/opt/so/conf/elasticsearch/users_roles} +elasticUsersFile=${ELASTIC_USERS_FILE:-/opt/so/saltstack/local/salt/elasticsearch/files/users} +elasticRolesFile=${ELASTIC_ROLES_FILE:-/opt/so/saltstack/local/salt/elasticsearch/files/users_roles} function fail() { msg=$1 diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index dd4af7696..5ee936f1c 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -174,8 +174,8 @@ syncesusers: cmd.run: - name: so-user sync - creates: - - /opt/so/conf/elasticsearch/users - - /opt/so/conf/elasticsearch/users_roles + - /opt/so/saltstack/local/salt/elasticsearch/files/users + - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles so-elasticsearch: docker_container.running: From b43e6c5d6bb0721bdbb0418e2cdeb93700e375c6 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 26 May 2021 13:51:24 -0400 Subject: [PATCH 24/76] Salt will handle auto-sync --- salt/common/tools/sbin/so-user | 5 ----- 1 file changed, 5 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 23034a6e9..1ff637d23 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -266,7 +266,6 @@ case "${operation}" in validateEmail "$email" updatePassword createUser "$email" - syncAll echo "Successfully added new user to SOC" check_container thehive && echo $password | so-thehive-user-add "$email" check_container fleet && echo $password | so-fleet-user-add "$email" @@ -282,7 +281,6 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateUser "$email" - syncAll echo "Successfully updated user" ;; @@ -291,7 +289,6 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'active' - syncAll echo "Successfully enabled user" check_container thehive && so-thehive-user-enable "$email" true check_container fleet && so-fleet-user-enable "$email" true @@ -302,7 +299,6 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'locked' - syncAll echo "Successfully disabled user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false @@ -313,7 +309,6 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" deleteUser "$email" - syncAll echo "Successfully deleted user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false From 4d991d3773f655ae510f7075f33bc3eee03dca7e Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Wed, 26 May 2021 14:52:10 -0400 Subject: [PATCH 25/76] propogate users and users_roles --- salt/elasticsearch/init.sls | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 65a3d2bca..017c135d2 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -37,6 +37,8 @@ {% set TEMPLATES = salt['pillar.get']('elasticsearch:templates', {}) %} {% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} +{% set ES_INCLUDED_NODES = ['so-standalone'] %} + vm.max_map_count: sysctl.present: - value: 262144 @@ -170,6 +172,35 @@ eslogdir: - group: 939 - makedirs: True +{% if grains.role in ES_INCLUDED_NODES %} +# Must run before elasticsearch docker container is started! +syncesusers: + cmd.run: + - name: so-user sync + - creates: + - /opt/so/saltstack/local/salt/elasticsearch/files/users + - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles +{% endif %} + +auth_users: + file.managed: + - name: /opt/so/conf/elasticsearch/users + - source: salt://elasticsearch/files/users + - require: +{% if grains.role in ES_INCLUDED_NODES %} + - cmd: syncesusers +{% endif %} + +auth_users_roles: + file.managed: + - name: /opt/so/conf/elasticsearch/users_roles + - source: salt://elasticsearch/files/users_roles +{% if grains.role in ES_INCLUDED_NODES %} + - require: + - cmd: syncesusers +{% endif %} + + so-elasticsearch: docker_container.running: - image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-elasticsearch:{{ VERSION }} From 7263e35a89273af973aefeb5cf91d87aa28da042 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Wed, 26 May 2021 14:52:59 -0400 Subject: [PATCH 26/76] happy little comment --- salt/elasticsearch/init.sls | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 017c135d2..84de1fd0b 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -37,6 +37,7 @@ {% set TEMPLATES = salt['pillar.get']('elasticsearch:templates', {}) %} {% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} +# used in this state to control who can run the so-users script {% set ES_INCLUDED_NODES = ['so-standalone'] %} vm.max_map_count: From dc8520df42c9b31ff6fc46f0329b45649def9342 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Wed, 26 May 2021 18:04:30 -0400 Subject: [PATCH 27/76] user curl.config for curl and elasticscripts --- salt/elasticsearch/auth.map.jinja | 2 +- salt/elasticsearch/init.sls | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/elasticsearch/auth.map.jinja b/salt/elasticsearch/auth.map.jinja index 147b0157b..c6f099025 100644 --- a/salt/elasticsearch/auth.map.jinja +++ b/salt/elasticsearch/auth.map.jinja @@ -2,6 +2,6 @@ True: { 'user': salt['pillar.get']('elasticsearch:auth:user'), 'pass': salt['pillar.get']('elasticsearch:auth:pass'), - 'elasticcurl':'curl --user ' ~ salt['pillar.get']('elasticsearch:auth:user') ~ ':' ~ salt['pillar.get']('elasticsearch:auth:pass') }, + 'elasticcurl':'curl -K /opt/so/conf/elasticsearch/curl.config' }, False: {'elasticcurl': 'curl'}, }, pillar='elasticsearch:auth:enabled', default=False) %} diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 84de1fd0b..9c0372684 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -292,6 +292,7 @@ elastic_curl_config: file.managed: - name: /opt/so/conf/elasticsearch/curl.config - mode: 600 + - contents: user = "{{ salt['pillar.get']('elasticsearch:auth:user') }}:{{ salt['pillar.get']('elasticsearch:auth:pass') }}" - show_changes: False {% endif %} {# if grains['role'] != 'so-helix' #} From 423793ecf9807bf02fdbe73546c834447b77f447 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Thu, 27 May 2021 13:50:22 -0400 Subject: [PATCH 28/76] remove vault pg from testing --- salt/firewall/portgroups.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/salt/firewall/portgroups.yaml b/salt/firewall/portgroups.yaml index 3a7316e98..1386267f5 100644 --- a/salt/firewall/portgroups.yaml +++ b/salt/firewall/portgroups.yaml @@ -89,9 +89,6 @@ firewall: - 514 udp: - 514 - vault: - tcp: - - 8200 wazuh_agent: tcp: - 1514 From 18926009d326ef41b5f408b839f2488fef45e8c4 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Fri, 28 May 2021 10:38:06 -0400 Subject: [PATCH 29/76] remove unneeded curl.config template --- salt/elasticsearch/files/curl.config | 1 - 1 file changed, 1 deletion(-) delete mode 100644 salt/elasticsearch/files/curl.config diff --git a/salt/elasticsearch/files/curl.config b/salt/elasticsearch/files/curl.config deleted file mode 100644 index e4633df6c..000000000 --- a/salt/elasticsearch/files/curl.config +++ /dev/null @@ -1 +0,0 @@ -user = "salt['pillar.get']('elasticsearch:auth:user'):salt['pillar.get']('elasticsearch:auth:pass')" From 63b31de2b841eb0212499a2d8b846425cb3fe405 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Fri, 28 May 2021 13:58:03 -0400 Subject: [PATCH 30/76] add additional users - manage file if user name isnt returned from grepping the file --- salt/elasticsearch/auth.sls | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls index e8ab1e378..187922d6e 100644 --- a/salt/elasticsearch/auth.sls +++ b/salt/elasticsearch/auth.sls @@ -5,8 +5,27 @@ elastic_auth_pillar: elasticsearch: auth: enabled: False - user: so_elastic - pass: {{ salt['random.get_str'](20) }} + users: + so_elastic_user: + user: so_elastic + pass: {{ salt['random.get_str'](20) }} + so_kibana_user: + user: so_kibana + pass: {{ salt['random.get_str'](20) }} + so_logstash_user: + user: so_logstash + pass: {{ salt['random.get_str'](20) }} + so_beats_user: + user: so_beats + pass: {{ salt['random.get_str'](20) }} + so_monitor_user: + user: so_monitor + pass: {{ salt['random.get_str'](20) }} # since we are generating a random password, and we don't want that to happen everytime - # a highstate runs, we only manage the file if it doesn't exist - - unless: ls /opt/so/saltstack/local/pillar/elasticsearch/auth.sls + # a highstate runs, we only manage the file each user isn't present in the file. if the + # pillar file doesn't exists, then the default vault provided to pillar.get should not + # be within the file either, so it should then be created + - unless: + {% for so_app_user in salt['pillar.get']('elasticsearch:auth:users', {'so_noapp_user': {'user': 'r@NDumu53Rd0NtDOoP'}}) %} + - grep {{ so_app_user.user }} /opt/so/saltstack/local/pillar/elasticsearch/auth.sls + {% endfor%} From 68abaa5e3c6c3efa873a2db6fa617c470a5abcf2 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Fri, 28 May 2021 14:03:21 -0400 Subject: [PATCH 31/76] update auth.map and curl.config to use new elasticsearch:auth pillar format --- salt/elasticsearch/auth.map.jinja | 4 ++-- salt/elasticsearch/init.sls | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/salt/elasticsearch/auth.map.jinja b/salt/elasticsearch/auth.map.jinja index c6f099025..3c3b42cdc 100644 --- a/salt/elasticsearch/auth.map.jinja +++ b/salt/elasticsearch/auth.map.jinja @@ -1,7 +1,7 @@ {% set ELASTICAUTH = salt['pillar.filter_by']({ True: { - 'user': salt['pillar.get']('elasticsearch:auth:user'), - 'pass': salt['pillar.get']('elasticsearch:auth:pass'), + 'user': salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user'), + 'pass': salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass'), 'elasticcurl':'curl -K /opt/so/conf/elasticsearch/curl.config' }, False: {'elasticcurl': 'curl'}, }, pillar='elasticsearch:auth:enabled', default=False) %} diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 7f287fa27..fb2927e99 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -293,7 +293,7 @@ elastic_curl_config: file.managed: - name: /opt/so/conf/elasticsearch/curl.config - mode: 600 - - contents: user = "{{ salt['pillar.get']('elasticsearch:auth:user') }}:{{ salt['pillar.get']('elasticsearch:auth:pass') }}" + - contents: user = "{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user') }}:{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass') }}" - show_changes: False {% endif %} {# if grains['role'] != 'so-helix' #} From edf60f80f707b5c65b853d87f49b9652c6a5d117 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Fri, 28 May 2021 15:26:26 -0400 Subject: [PATCH 32/76] manager and common states now require elasticsearch.auth state --- salt/common/init.sls | 11 ++++++++++- salt/manager/init.sls | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/salt/common/init.sls b/salt/common/init.sls index d61806a1a..33c1f28df 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -3,6 +3,12 @@ {% set role = grains.id.split('_') | last %} {% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} +{% set ES_INCLUDED_NODES = ['so-standalone'] %} + +{% if grains.role in ES_INCLUDED_NODES %} +include: + - elasticsearch.auth +{% %} # Remove variables.txt from /tmp - This is temp rmvariablesfile: @@ -179,7 +185,10 @@ utilsyncscripts: - source: salt://common/tools/sbin - defaults: ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} - +{% if grains.role in ES_INCLUDED_NODES %} + - require: + - file: elastic_auth_pillar +{% endif %} {% if role in ['eval', 'standalone', 'sensor', 'heavynode'] %} # Add sensor cleanup diff --git a/salt/manager/init.sls b/salt/manager/init.sls index 91635eb59..91be3136f 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -20,6 +20,9 @@ {% set MANAGER = salt['grains.get']('master') %} {% set STRELKA_RULES = salt['pillar.get']('strelka:rules', '1') %} +include: + - elasticsearch.auth + socore_own_saltstack: file.directory: - name: /opt/so/saltstack From b8a10f2e8680792ca4c56eb2f650df0699d51eee Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 28 May 2021 14:49:43 -0400 Subject: [PATCH 33/76] Support multiple elastic system users --- salt/common/tools/sbin/so-common | 3 +- salt/common/tools/sbin/so-user | 51 ++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/salt/common/tools/sbin/so-common b/salt/common/tools/sbin/so-common index b48f84b90..a89f93eea 100755 --- a/salt/common/tools/sbin/so-common +++ b/salt/common/tools/sbin/so-common @@ -252,6 +252,7 @@ lookup_salt_value() { key=$1 group=$2 kind=$3 + output=${4:-newline_values_only} if [ -z "$kind" ]; then kind=pillar @@ -261,7 +262,7 @@ lookup_salt_value() { group=${group}: fi - salt-call --no-color ${kind}.get ${group}${key} --out=newline_values_only + salt-call --no-color ${kind}.get ${group}${key} --out=${output} } lookup_pillar() { diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 1ff637d23..d8d8fe34a 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -136,17 +136,56 @@ function createElasticTmpFile() { echo "$tmpFile" } +function syncElasticSystemUser() { + json=$1 + userid=$2 + usersFile=$3 + + user=$(echo "$json" | jq -r ".local.users.$userid.user") + pass=$(echo "$json" | jq -r ".local.users.$userid.pass") + + [[ -z "$user" || -z "$pass" ]] && fail "Elastic auth credentials for system user '$userid' are missing" + hash=$(hashPassword "$pass") + + echo "${user}:${hash}" >> "$usersFile" +} + +function syncElasticSystemRole() { + json=$1 + userid=$2 + role=$3 + rolesFile=$4 + + user=$(echo "$json" | jq -r ".local.users.$userid.user") + + [[ -z "$user" ]] && fail "Elastic auth credentials for system user '$userid' are missing" + + echo "${role}:${user}" >> "$rolesFile" +} + function syncElastic() { usersFileTmp=$(createElasticTmpFile "${elasticUsersFile}") rolesFileTmp=$(createElasticTmpFile "${elasticRolesFile}") - sysUser=$(lookup_pillar "auth:user" "elasticsearch") - sysPass=$(lookup_pillar "auth:pass" "elasticsearch") - [[ -z "$sysUser" || -z "$sysPass" ]] && fail "Elastic auth credentials for system user are missing" - sysHash=$(hashPassword "$sysPass") + authPillarJson=$(lookup_salt_value "auth" "elasticsearch" "pillar" "json") + + syncElasticSystemUser "$authPillarJson" "so_elastic_user" "$usersFileTmp" + syncElasticSystemRole "$authPillarJson" "so_elastic_user" "superuser" "$rolesFileTmp" + + syncElasticSystemUser "$authPillarJson" "so_kibana_user" "$usersFileTmp" + syncElasticSystemRole "$authPillarJson" "so_kibana_user" "kibana_system" "$rolesFileTmp" + + syncElasticSystemUser "$authPillarJson" "so_logstash_user" "$usersFileTmp" + syncElasticSystemRole "$authPillarJson" "so_logstash_user" "logstash_system" "$rolesFileTmp" + + syncElasticSystemUser "$authPillarJson" "so_beats_user" "$usersFileTmp" + syncElasticSystemRole "$authPillarJson" "so_beats_user" "beats_system" "$rolesFileTmp" + + syncElasticSystemUser "$authPillarJson" "so_monitor_user" "$usersFileTmp" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_collector" "$rolesFileTmp" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_agent" "$rolesFileTmp" # Generate the new users file - echo "${sysUser}:${sysHash}" >> "$usersFileTmp" echo "select '{\"user\":\"' || ici.identifier || '\", \"data\":' || ic.config || '}'" \ "from identity_credential_identifiers ici, identity_credentials ic " \ "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ @@ -159,7 +198,7 @@ function syncElastic() { [[ $? != 0 ]] && fail "Unable to create users file: $elasticUsersFile" # Generate the new users_roles file - echo "superuser:${sysUser}" >> "$rolesFileTmp" + echo "select 'superuser:' || ici.identifier " \ "from identity_credential_identifiers ici, identity_credentials ic " \ "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ From 3aad5a30e96f88830aad729baa200257d49092fb Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Fri, 28 May 2021 18:28:53 -0400 Subject: [PATCH 34/76] fix logic on password created in pillar and fix how me manage --- salt/elasticsearch/auth.sls | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls index 187922d6e..303383cfe 100644 --- a/salt/elasticsearch/auth.sls +++ b/salt/elasticsearch/auth.sls @@ -1,3 +1,9 @@ +{% set so_elastic_user_pass = salt['random.get_str'](20) %} +{% set so_kibana_user_pass = salt['random.get_str'](20) %} +{% set so_logstash_user_pass = salt['random.get_str'](20) %} +{% set so_beats_user_pass = salt['random.get_str'](20) %} +{% set so_monitor_user_pass = salt['random.get_str'](20) %} + elastic_auth_pillar: file.managed: - name: /opt/so/saltstack/local/pillar/elasticsearch/auth.sls @@ -8,24 +14,26 @@ elastic_auth_pillar: users: so_elastic_user: user: so_elastic - pass: {{ salt['random.get_str'](20) }} + pass: {{ so_elastic_user_pass }} so_kibana_user: user: so_kibana - pass: {{ salt['random.get_str'](20) }} + pass: {{ so_kibana_user_pass }} so_logstash_user: user: so_logstash - pass: {{ salt['random.get_str'](20) }} + pass: {{ so_logstash_user_pass }} so_beats_user: user: so_beats - pass: {{ salt['random.get_str'](20) }} + pass: {{ so_beats_user_pass }} so_monitor_user: user: so_monitor - pass: {{ salt['random.get_str'](20) }} + pass: {{ so_monitor_user_pass }} # since we are generating a random password, and we don't want that to happen everytime # a highstate runs, we only manage the file each user isn't present in the file. if the # pillar file doesn't exists, then the default vault provided to pillar.get should not # be within the file either, so it should then be created +{% if salt['pillar.get']('elasticsearch:auth', False) %} - unless: - {% for so_app_user in salt['pillar.get']('elasticsearch:auth:users', {'so_noapp_user': {'user': 'r@NDumu53Rd0NtDOoP'}}) %} + {% for so_app_user in salt['pillar.get']('elasticsearch:auth:users') %} - grep {{ so_app_user.user }} /opt/so/saltstack/local/pillar/elasticsearch/auth.sls {% endfor%} +{% endif %} From 47b56e78b38377bb0284abbf983a1b999ada8afe Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 28 May 2021 20:07:51 -0400 Subject: [PATCH 35/76] Fix missing endif --- salt/common/init.sls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/common/init.sls b/salt/common/init.sls index 33c1f28df..88b5c790b 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -8,7 +8,7 @@ {% if grains.role in ES_INCLUDED_NODES %} include: - elasticsearch.auth -{% %} +{% endif %} # Remove variables.txt from /tmp - This is temp rmvariablesfile: From a42a406f532fc26cc58ab0c38c24f25f22eb8275 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Sat, 29 May 2021 07:52:08 -0400 Subject: [PATCH 36/76] Remove extra users file mounts; disable elastic anon access when auth enabled --- salt/elasticsearch/files/elasticsearch.yml | 2 ++ salt/elasticsearch/init.sls | 2 -- salt/kibana/etc/kibana.yml | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/salt/elasticsearch/files/elasticsearch.yml b/salt/elasticsearch/files/elasticsearch.yml index fed45bf79..de6b99000 100644 --- a/salt/elasticsearch/files/elasticsearch.yml +++ b/salt/elasticsearch/files/elasticsearch.yml @@ -30,11 +30,13 @@ xpack.security.http.ssl.client_authentication: none xpack.security.http.ssl.key: /usr/share/elasticsearch/config/elasticsearch.key xpack.security.http.ssl.certificate: /usr/share/elasticsearch/config/elasticsearch.crt xpack.security.http.ssl.certificate_authorities: /usr/share/elasticsearch/config/ca.crt +{% if not salt['pillar.get']('elasticsearch:auth:enabled', False) %} xpack.security.authc: anonymous: username: anonymous_user roles: superuser authz_exception: true +{% endif %} node.name: {{ grains.host }} script.max_compilations_rate: 1000/1m {%- if TRUECLUSTER is sameas true %} diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index fb2927e99..b75833952 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -234,8 +234,6 @@ so-elasticsearch: - binds: - /opt/so/conf/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - /opt/so/conf/elasticsearch/log4j2.properties:/usr/share/elasticsearch/config/log4j2.properties:ro - - /opt/so/conf/elasticsearch/users:/usr/share/elasticsearch/config/users:ro - - /opt/so/conf/elasticsearch/users_roles:/usr/share/elasticsearch/config/users_roles:ro - /nsm/elasticsearch:/usr/share/elasticsearch/data:rw - /opt/so/log/elasticsearch:/var/log/elasticsearch:rw - /opt/so/conf/ca/cacerts:/etc/pki/ca-trust/extracted/java/cacerts:ro diff --git a/salt/kibana/etc/kibana.yml b/salt/kibana/etc/kibana.yml index 856f87909..501d93c8a 100644 --- a/salt/kibana/etc/kibana.yml +++ b/salt/kibana/etc/kibana.yml @@ -14,7 +14,9 @@ elasticsearch.requestTimeout: 90000 logging.dest: /var/log/kibana/kibana.log telemetry.enabled: false security.showInsecureClusterWarning: false +{% if not salt['pillar.get']('elasticsearch:auth:enabled', False) %} xpack.security.authc.providers: anonymous.anonymous1: order: 0 credentials: "elasticsearch_anonymous_user" +{% endif %} \ No newline at end of file From 1aa2852ed6c60e149aa79578d500c6a4cde2afae Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 1 Jun 2021 08:35:43 -0400 Subject: [PATCH 37/76] fix logic --- salt/elasticsearch/auth.sls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls index 303383cfe..704d743ce 100644 --- a/salt/elasticsearch/auth.sls +++ b/salt/elasticsearch/auth.sls @@ -33,7 +33,7 @@ elastic_auth_pillar: # be within the file either, so it should then be created {% if salt['pillar.get']('elasticsearch:auth', False) %} - unless: - {% for so_app_user in salt['pillar.get']('elasticsearch:auth:users') %} - - grep {{ so_app_user.user }} /opt/so/saltstack/local/pillar/elasticsearch/auth.sls + {% for so_app_user, values in salt['pillar.get']('elasticsearch:auth:users', {'so_noapp_user': {'user': 'r@NDumu53Rd0NtDOoP'}}).items() %} + - grep {{ values.user }} /opt/so/saltstack/local/pillar/elasticsearch/auth.sls {% endfor%} {% endif %} From f87dce8ec1629a6254d4e7088c629bea79908e82 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 1 Jun 2021 09:38:07 -0400 Subject: [PATCH 38/76] generate pillar file if auth enabled or not --- salt/elasticsearch/auth.sls | 2 -- 1 file changed, 2 deletions(-) diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls index 704d743ce..748e50d0b 100644 --- a/salt/elasticsearch/auth.sls +++ b/salt/elasticsearch/auth.sls @@ -31,9 +31,7 @@ elastic_auth_pillar: # a highstate runs, we only manage the file each user isn't present in the file. if the # pillar file doesn't exists, then the default vault provided to pillar.get should not # be within the file either, so it should then be created -{% if salt['pillar.get']('elasticsearch:auth', False) %} - unless: {% for so_app_user, values in salt['pillar.get']('elasticsearch:auth:users', {'so_noapp_user': {'user': 'r@NDumu53Rd0NtDOoP'}}).items() %} - grep {{ values.user }} /opt/so/saltstack/local/pillar/elasticsearch/auth.sls {% endfor%} -{% endif %} From ed8c85df2ba86a18166d21d1803d95db23a076f0 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Tue, 1 Jun 2021 10:26:33 -0400 Subject: [PATCH 39/76] Only sync web users if teh sqlite db exists --- salt/common/tools/sbin/so-user | 48 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index d8d8fe34a..cc3a0756c 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -185,29 +185,33 @@ function syncElastic() { syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_collector" "$rolesFileTmp" syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_agent" "$rolesFileTmp" - # Generate the new users file - echo "select '{\"user\":\"' || ici.identifier || '\", \"data\":' || ic.config || '}'" \ - "from identity_credential_identifiers ici, identity_credentials ic " \ - "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ - "order by ici.identifier;" | \ - sqlite3 "$databasePath" | \ - jq -r '.user + ":" + .data.hashed_password' \ - >> "$usersFileTmp" - [[ $? != 0 ]] && fail "Unable to read credential hashes from database" - mv -f "$usersFileTmp" "$elasticUsersFile" - [[ $? != 0 ]] && fail "Unable to create users file: $elasticUsersFile" + if [[ -f "$databasePath" ]]; then + # Generate the new users file + echo "select '{\"user\":\"' || ici.identifier || '\", \"data\":' || ic.config || '}'" \ + "from identity_credential_identifiers ici, identity_credentials ic " \ + "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ + "order by ici.identifier;" | \ + sqlite3 "$databasePath" | \ + jq -r '.user + ":" + .data.hashed_password' \ + >> "$usersFileTmp" + [[ $? != 0 ]] && fail "Unable to read credential hashes from database" + mv -f "$usersFileTmp" "$elasticUsersFile" + [[ $? != 0 ]] && fail "Unable to create users file: $elasticUsersFile" - # Generate the new users_roles file - - echo "select 'superuser:' || ici.identifier " \ - "from identity_credential_identifiers ici, identity_credentials ic " \ - "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ - "order by ici.identifier;" | \ - sqlite3 "$databasePath" \ - >> "$rolesFileTmp" - [[ $? != 0 ]] && fail "Unable to read credential IDs from database" - mv -f "$rolesFileTmp" "$elasticRolesFile" - [[ $? != 0 ]] && fail "Unable to create users file: $elasticRolesFile" + # Generate the new users_roles file + + echo "select 'superuser:' || ici.identifier " \ + "from identity_credential_identifiers ici, identity_credentials ic " \ + "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ + "order by ici.identifier;" | \ + sqlite3 "$databasePath" \ + >> "$rolesFileTmp" + [[ $? != 0 ]] && fail "Unable to read credential IDs from database" + mv -f "$rolesFileTmp" "$elasticRolesFile" + [[ $? != 0 ]] && fail "Unable to create users file: $elasticRolesFile" + else + info "Database file does not exist yet, skipping users export" + fi } function syncAll() { From d25a439bd4706432fbfc7f0f810d03284732b250 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 1 Jun 2021 10:53:58 -0400 Subject: [PATCH 40/76] more changes --- pillar/top.sls | 9 +++++++++ salt/common/init.sls | 17 +++++++---------- salt/elasticsearch/init.sls | 27 --------------------------- salt/manager/init.sls | 16 ++++++++++++++++ salt/top.sls | 3 +-- setup/so-setup | 1 + 6 files changed, 34 insertions(+), 39 deletions(-) diff --git a/pillar/top.sls b/pillar/top.sls index 8bd67c174..ff4cb5787 100644 --- a/pillar/top.sls +++ b/pillar/top.sls @@ -22,6 +22,9 @@ base: '*_manager or *_managersearch': - match: compound - data.* +{% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} + - elasticsearch.auth +{% endif %} - secrets - global - minions.{{ grains.id }} @@ -38,6 +41,9 @@ base: - secrets - healthcheck.eval - elasticsearch.eval +{% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} + - elasticsearch.auth +{% endif %} - global - minions.{{ grains.id }} @@ -91,5 +97,8 @@ base: - zeeklogs - secrets - elasticsearch.eval +{% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} + - elasticsearch.auth +{% endif %} - global - minions.{{ grains.id }} diff --git a/salt/common/init.sls b/salt/common/init.sls index 33c1f28df..09a0db934 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -3,12 +3,6 @@ {% set role = grains.id.split('_') | last %} {% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} -{% set ES_INCLUDED_NODES = ['so-standalone'] %} - -{% if grains.role in ES_INCLUDED_NODES %} -include: - - elasticsearch.auth -{% %} # Remove variables.txt from /tmp - This is temp rmvariablesfile: @@ -174,6 +168,13 @@ alwaysupdated: Etc/UTC: timezone.system +elastic_curl_config: + file.managed: + - name: /opt/so/conf/elasticsearch/curl.config + - source: salt://elasticsearch/curl.config + - mode: 600 + - show_changes: False + # Sync some Utilities utilsyncscripts: file.recurse: @@ -185,10 +186,6 @@ utilsyncscripts: - source: salt://common/tools/sbin - defaults: ELASTICCURL: {{ ELASTICAUTH.elasticcurl }} -{% if grains.role in ES_INCLUDED_NODES %} - - require: - - file: elastic_auth_pillar -{% endif %} {% if role in ['eval', 'standalone', 'sensor', 'heavynode'] %} # Add sensor cleanup diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index fb2927e99..4d5ce4921 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -37,8 +37,6 @@ {% set TEMPLATES = salt['pillar.get']('elasticsearch:templates', {}) %} {% from 'elasticsearch/auth.map.jinja' import ELASTICAUTH with context %} -# used in this state to control who can run the so-users script -{% set ES_INCLUDED_NODES = ['so-standalone'] %} vm.max_map_count: sysctl.present: @@ -173,33 +171,15 @@ eslogdir: - group: 939 - makedirs: True -{% if grains.role in ES_INCLUDED_NODES %} -# Must run before elasticsearch docker container is started! -syncesusers: - cmd.run: - - name: so-user sync - - creates: - - /opt/so/saltstack/local/salt/elasticsearch/files/users - - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles -{% endif %} - auth_users: file.managed: - name: /opt/so/conf/elasticsearch/users - source: salt://elasticsearch/files/users - - require: -{% if grains.role in ES_INCLUDED_NODES %} - - cmd: syncesusers -{% endif %} auth_users_roles: file.managed: - name: /opt/so/conf/elasticsearch/users_roles - source: salt://elasticsearch/files/users_roles -{% if grains.role in ES_INCLUDED_NODES %} - - require: - - cmd: syncesusers -{% endif %} so-elasticsearch: docker_container.running: @@ -289,13 +269,6 @@ so-elasticsearch-templates: - template: jinja {% endif %} -elastic_curl_config: - file.managed: - - name: /opt/so/conf/elasticsearch/curl.config - - mode: 600 - - contents: user = "{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user') }}:{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass') }}" - - show_changes: False - {% endif %} {# if grains['role'] != 'so-helix' #} {% else %} diff --git a/salt/manager/init.sls b/salt/manager/init.sls index 91be3136f..7ef489496 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -105,6 +105,22 @@ strelka_yara_update: - name: '/usr/sbin/so-yara-update >> /nsm/strelka/log/yara-update.log 2>&1' - hour: '7' - minute: '1' + +elastic_curl_config_distributed: + file.managed: + - name: /opt/so/saltstack/local/salt/elasticsearch/curl.config + - mode: 600 + - contents: user = "{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user') }}:{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass') }}" + - show_changes: False + +# Must run before elasticsearch docker container is started! +syncesusers: + cmd.run: + - name: so-user sync + - creates: + - /opt/so/saltstack/local/salt/elasticsearch/files/users + - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles + {% else %} {{sls}}_state_not_allowed: diff --git a/salt/top.sls b/salt/top.sls index f3f2958ae..a063c4279 100644 --- a/salt/top.sls +++ b/salt/top.sls @@ -238,7 +238,6 @@ base: {%- endif %} {%- if ELASTICSEARCH %} - elasticsearch - - elasticsearch.auth {%- endif %} {%- if LOGSTASH %} - logstash @@ -261,7 +260,7 @@ base: - filebeat {%- endif %} {%- if CURATOR %} - - curator + - curator0 {%- endif %} {%- if ELASTALERT %} - elastalert diff --git a/setup/so-setup b/setup/so-setup index 4c364ded6..6d2f6ac27 100755 --- a/setup/so-setup +++ b/setup/so-setup @@ -752,6 +752,7 @@ echo "1" > /root/accept_changes set_progress_str 60 "$(print_salt_state_apply 'manager')" salt-call state.apply -l info manager >> $setup_log 2>&1 + bash /opt/so/saltstack/default/salt/common/tools/sbin/so-elastic-auth fi set_progress_str 61 "$(print_salt_state_apply 'firewall')" From bfaffbc87e2b7b1ab7d52612178c0d632679d9c0 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 1 Jun 2021 11:15:28 -0400 Subject: [PATCH 41/76] add reactor and beacon for sqlite db --- files/salt/master/master | 2 ++ salt/manager/files/beacons.conf | 5 +++++ salt/manager/init.sls | 5 +++++ salt/reactor/kratos.sls | 5 +++++ 4 files changed, 17 insertions(+) create mode 100644 salt/manager/files/beacons.conf create mode 100644 salt/reactor/kratos.sls diff --git a/files/salt/master/master b/files/salt/master/master index 93e8ff938..675556d14 100644 --- a/files/salt/master/master +++ b/files/salt/master/master @@ -67,3 +67,5 @@ peer: reactor: - 'so/fleet': - salt://reactor/fleet.sls + - salt/beacon/*/inotify//watch_sqlite.db: + - salt://reactor/kratos.sls diff --git a/salt/manager/files/beacons.conf b/salt/manager/files/beacons.conf new file mode 100644 index 000000000..b1cca51ba --- /dev/null +++ b/salt/manager/files/beacons.conf @@ -0,0 +1,5 @@ +beacons: + watch_sqlite.db: + - files: + /opt/so/conf/kratos/db/sqlite.db: {} + - beacon_module: inotify diff --git a/salt/manager/init.sls b/salt/manager/init.sls index 7ef489496..10466d019 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -121,6 +121,11 @@ syncesusers: - /opt/so/saltstack/local/salt/elasticsearch/files/users - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles +beacons_config: + file.managed: + - name: /etc/salt/minion.d/beacons.conf + - source: salt://manager/files/beacons.conf + {% else %} {{sls}}_state_not_allowed: diff --git a/salt/reactor/kratos.sls b/salt/reactor/kratos.sls new file mode 100644 index 000000000..a465f134c --- /dev/null +++ b/salt/reactor/kratos.sls @@ -0,0 +1,5 @@ +so_user_sync: + local.cmd.run: + - tgt: {{ data['data']['id'] }} + - arg: + - so-user sync From ef00695b07ef4d9cac79113928113ba32ab41940 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 1 Jun 2021 11:31:50 -0400 Subject: [PATCH 42/76] fix typo --- salt/top.sls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/top.sls b/salt/top.sls index a063c4279..8a12aaa26 100644 --- a/salt/top.sls +++ b/salt/top.sls @@ -260,7 +260,7 @@ base: - filebeat {%- endif %} {%- if CURATOR %} - - curator0 + - curator {%- endif %} {%- if ELASTALERT %} - elastalert From 7a59bee315589c75d74996e314ea3e4988e17f07 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Tue, 1 Jun 2021 12:48:53 -0400 Subject: [PATCH 43/76] Add so-elastic-auth script --- salt/common/tools/sbin/so-elastic-auth | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 salt/common/tools/sbin/so-elastic-auth diff --git a/salt/common/tools/sbin/so-elastic-auth b/salt/common/tools/sbin/so-elastic-auth new file mode 100644 index 000000000..b15b04c0f --- /dev/null +++ b/salt/common/tools/sbin/so-elastic-auth @@ -0,0 +1,58 @@ +#!/bin/bash + +# Copyright 2014,2015,2016,2017,2018,2019,2020,2021 Security Onion Solutions, LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +. /usr/sbin/so-common + +ES_AUTH_PILLAR=${ELASTIC_AUTH_PILLAR:-/opt/so/saltstack/local/pillar/elasticsearch/auth.sls} +ES_USERS_FILE=${ELASTIC_USERS_FILE:-/opt/so/saltstack/local/salt/elasticsearch/files/users} + +authEnable=${1:-true} + +if ! grep -q "enabled: " "$ES_AUTH_PILLAR"; then + echo "Elastic auth pillar file is invalid. Unable to proceed." + exit 1 +fi + +if [[ "$authEnable" == "true" ]]; then + if grep -q "enabled: False" "$ES_AUTH_PILLAR"; then + sed -i 's/enabled: False/enabled: True/g' "$ES_AUTH_PILLAR" + echo "Applying highstate - this may take a few minutes..." + salt-call state.highstate queue=True + echo "Elastic auth is now enabled." + if grep -q "argon" "$ES_USERS_FILE"; then + echo "" + echo "IMPORTANT: The following users will need to change their password, after logging into SOC, in order to access Kibana:" + grep argon "$ES_USERS" | cut -d ":" -f 1 + fi + else + echo "Auth is already enabled." + fi +elif [[ "$authEnable" == "false" ]]; then + if grep -q "enabled: True" "$ES_AUTH_PILLAR"; then + sed -i 's/enabled: True/enabled: False/g' "$ES_AUTH_PILLAR" + echo "Applying highstate - this may take a few minutes..." + salt-call state.highstate queue=True + echo "Elastic auth is now disabled." + else + echo "Auth is already disabled." + fi +else + echo "Usage: $0 " + echo "" + echo "Enables Elastic authentication. Defaults to true." + echo "" +fi From 2a2247e1da55bc5b859c6d4bc6fdd9113a1e5946 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Tue, 1 Jun 2021 14:45:01 -0400 Subject: [PATCH 44/76] Additional so-user sync adjustments --- salt/common/tools/sbin/so-user | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index cc3a0756c..9ea6c0310 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -42,6 +42,8 @@ databasePath=${KRATOS_DB_PATH:-/opt/so/conf/kratos/db/db.sqlite} bcryptRounds=${BCRYPT_ROUNDS:-12} elasticUsersFile=${ELASTIC_USERS_FILE:-/opt/so/saltstack/local/salt/elasticsearch/files/users} elasticRolesFile=${ELASTIC_ROLES_FILE:-/opt/so/saltstack/local/salt/elasticsearch/files/users_roles} +esUID=${ELASTIC_UID:-930} +esGID=${ELASTIC_GID:-930} function fail() { msg=$1 @@ -132,7 +134,7 @@ function createElasticTmpFile() { tmpFile=${filename}.tmp truncate -s 0 "$tmpFile" chmod 600 "$tmpFile" - chown elasticsearch:elasticsearch "$tmpFile" + chown "${esUID}:${esGID}" "$tmpFile" echo "$tmpFile" } @@ -195,8 +197,6 @@ function syncElastic() { jq -r '.user + ":" + .data.hashed_password' \ >> "$usersFileTmp" [[ $? != 0 ]] && fail "Unable to read credential hashes from database" - mv -f "$usersFileTmp" "$elasticUsersFile" - [[ $? != 0 ]] && fail "Unable to create users file: $elasticUsersFile" # Generate the new users_roles file @@ -207,11 +207,16 @@ function syncElastic() { sqlite3 "$databasePath" \ >> "$rolesFileTmp" [[ $? != 0 ]] && fail "Unable to read credential IDs from database" - mv -f "$rolesFileTmp" "$elasticRolesFile" - [[ $? != 0 ]] && fail "Unable to create users file: $elasticRolesFile" else info "Database file does not exist yet, skipping users export" fi + + # Move the temp files over onto the final files + mv -f "$usersFileTmp" "$elasticUsersFile" + [[ $? != 0 ]] && fail "Unable to create users file: $elasticUsersFile" + + mv -f "$rolesFileTmp" "$elasticRolesFile" + [[ $? != 0 ]] && fail "Unable to create users file: $elasticRolesFile" } function syncAll() { From 867613669d6e8e556a0c78187e6001d1e23af727 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 1 Jun 2021 17:01:03 -0400 Subject: [PATCH 45/76] changes for syncing users --- files/salt/master/master | 4 +++- salt/common/init.sls | 1 + salt/manager/files/beacons.conf | 6 ++++-- salt/manager/init.sls | 3 +++ salt/reactor/kratos.sls | 2 +- salt/salt/helper-packages.sls | 9 ++++++++- salt/salt/map.jinja | 4 +++- 7 files changed, 23 insertions(+), 6 deletions(-) diff --git a/files/salt/master/master b/files/salt/master/master index 675556d14..e7c6030dd 100644 --- a/files/salt/master/master +++ b/files/salt/master/master @@ -67,5 +67,7 @@ peer: reactor: - 'so/fleet': - salt://reactor/fleet.sls - - salt/beacon/*/inotify//watch_sqlite.db: + - salt/beacon/*/watch_sqlite_db//opt/so/conf/kratos/db/sqlite.db - salt://reactor/kratos.sls + + diff --git a/salt/common/init.sls b/salt/common/init.sls index 09a0db934..9d20de62b 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -174,6 +174,7 @@ elastic_curl_config: - source: salt://elasticsearch/curl.config - mode: 600 - show_changes: False + - makedirs: True # Sync some Utilities utilsyncscripts: diff --git a/salt/manager/files/beacons.conf b/salt/manager/files/beacons.conf index b1cca51ba..c40fe83cb 100644 --- a/salt/manager/files/beacons.conf +++ b/salt/manager/files/beacons.conf @@ -1,5 +1,7 @@ beacons: - watch_sqlite.db: + watch_sqlite_db: - files: - /opt/so/conf/kratos/db/sqlite.db: {} + /opt/so/conf/kratos/db/sqlite.db: + mask: + - modify - beacon_module: inotify diff --git a/salt/manager/init.sls b/salt/manager/init.sls index 10466d019..9ae39e9a8 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -22,6 +22,7 @@ include: - elasticsearch.auth + - salt.minion socore_own_saltstack: file.directory: @@ -125,6 +126,8 @@ beacons_config: file.managed: - name: /etc/salt/minion.d/beacons.conf - source: salt://manager/files/beacons.conf + - onchanges_in: + - service: salt_minion_service {% else %} diff --git a/salt/reactor/kratos.sls b/salt/reactor/kratos.sls index a465f134c..fb90cc164 100644 --- a/salt/reactor/kratos.sls +++ b/salt/reactor/kratos.sls @@ -2,4 +2,4 @@ so_user_sync: local.cmd.run: - tgt: {{ data['data']['id'] }} - arg: - - so-user sync + - /usr/sbin/so-user sync diff --git a/salt/salt/helper-packages.sls b/salt/salt/helper-packages.sls index 93ad76a22..c26cdc7c0 100644 --- a/salt/salt/helper-packages.sls +++ b/salt/salt/helper-packages.sls @@ -1,3 +1,10 @@ +{% from 'salt/map.jinja' import PYINOTIFYPACKAGE with context%} +{% from 'salt/map.jinja' import PYTHONINSTALLER with context%} + patch_package: pkg.installed: - - name: patch \ No newline at end of file + - name: patch + +pyinotify: + {{PYTHONINSTALLER}}.installed: + - name: {{ PYINOTIFYPACKAGE }} diff --git a/salt/salt/map.jinja b/salt/salt/map.jinja index b0b9ffb2a..4b9577319 100644 --- a/salt/salt/map.jinja +++ b/salt/salt/map.jinja @@ -11,6 +11,7 @@ {% set PYTHON3INFLUX= 'influxdb == ' ~ PYTHONINFLUXVERSION %} {% set PYTHON3INFLUXDEPS= ['certifi', 'chardet', 'python-dateutil', 'pytz', 'requests'] %} {% set PYTHONINSTALLER = 'pip' %} + {% set PYINOTIFYPACKAGE = 'pyinotify' %} {% else %} {% set SPLITCHAR = '-' %} {% set SALTNOTHELD = salt['cmd.run']('yum versionlock list | grep -q salt ; echo $?', python_shell=True) %} @@ -21,6 +22,7 @@ {% set PYTHON3INFLUX= 'securityonion-python3-influxdb' %} {% set PYTHON3INFLUXDEPS= ['python36-certifi', 'python36-chardet', 'python36-dateutil', 'python36-pytz', 'python36-requests'] %} {% set PYTHONINSTALLER = 'pkg' %} + {% set PYINOTIFYPACKAGE = 'securityonion-python3-pyinotify' %} {% endif %} {% set INSTALLEDSALTVERSION = salt['pkg.version']('salt-minion').split(SPLITCHAR)[0] %} @@ -33,4 +35,4 @@ {% endif %} {% else %} {% set UPGRADECOMMAND = 'echo Already running Salt Minion version ' ~ SALTVERSION %} -{% endif %} \ No newline at end of file +{% endif %} From 7b68c1bc9bb37fc8b6135ab502b98ea91cd01484 Mon Sep 17 00:00:00 2001 From: m0duspwnens Date: Tue, 1 Jun 2021 17:45:52 -0400 Subject: [PATCH 46/76] fix typo --- files/salt/master/master | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/salt/master/master b/files/salt/master/master index e7c6030dd..5db41fb90 100644 --- a/files/salt/master/master +++ b/files/salt/master/master @@ -67,7 +67,7 @@ peer: reactor: - 'so/fleet': - salt://reactor/fleet.sls - - salt/beacon/*/watch_sqlite_db//opt/so/conf/kratos/db/sqlite.db + - 'salt/beacon/*/watch_sqlite_db//opt/so/conf/kratos/db/sqlite.db': - salt://reactor/kratos.sls From 7aede4d058ed26b190d3f22d845b57f4f56fc38e Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 2 Jun 2021 09:01:16 -0400 Subject: [PATCH 47/76] Persist chown/chmod settings on users/roles files --- salt/common/tools/sbin/so-user | 4 ++-- salt/elasticsearch/init.sls | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 9ea6c0310..15a71edfa 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -208,7 +208,7 @@ function syncElastic() { >> "$rolesFileTmp" [[ $? != 0 ]] && fail "Unable to read credential IDs from database" else - info "Database file does not exist yet, skipping users export" + echo "Database file does not exist yet, skipping users export" fi # Move the temp files over onto the final files @@ -388,4 +388,4 @@ case "${operation}" in ;; esac -exit 0 \ No newline at end of file +exit 0 diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 86d7623d0..0bf442587 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -175,11 +175,17 @@ auth_users: file.managed: - name: /opt/so/conf/elasticsearch/users - source: salt://elasticsearch/files/users + - user: 930 + - group: 930 + - mode: 600 auth_users_roles: file.managed: - name: /opt/so/conf/elasticsearch/users_roles - source: salt://elasticsearch/files/users_roles + - user: 930 + - group: 930 + - mode: 600 so-elasticsearch: docker_container.running: From 20e896cacf0616740f141fd8e2fb59090b778b55 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 2 Jun 2021 12:17:15 -0400 Subject: [PATCH 48/76] Update all configs to pass user/pass to ES --- salt/curator/files/curator.yml | 4 ++++ salt/elastalert/defaults.yaml | 8 +++++--- salt/filebeat/etc/filebeat.yml | 4 ++++ salt/kibana/etc/kibana.yml | 8 +++++--- .../pipelines/config/so/9000_output_zeek.conf.jinja | 4 ++++ .../pipelines/config/so/9002_output_import.conf.jinja | 4 ++++ .../pipelines/config/so/9004_output_flow.conf.jinja | 4 ++++ .../pipelines/config/so/9033_output_snort.conf.jinja | 4 ++++ .../pipelines/config/so/9034_output_syslog.conf.jinja | 4 ++++ .../pipelines/config/so/9100_output_osquery.conf.jinja | 4 ++++ .../config/so/9101_output_osquery_livequery.conf.jinja | 4 ++++ .../pipelines/config/so/9200_output_firewall.conf.jinja | 4 ++++ .../pipelines/config/so/9400_output_suricata.conf.jinja | 4 ++++ .../pipelines/config/so/9500_output_beats.conf.jinja | 4 ++++ .../pipelines/config/so/9600_output_ossec.conf.jinja | 4 ++++ .../pipelines/config/so/9700_output_strelka.conf.jinja | 4 ++++ salt/soc/files/soc/soc.json | 6 ++++-- salt/soctopus/files/SOCtopus.conf | 7 ++++--- salt/telegraf/etc/telegraf.conf | 6 ++++++ 19 files changed, 80 insertions(+), 11 deletions(-) diff --git a/salt/curator/files/curator.yml b/salt/curator/files/curator.yml index 7d86ccc04..a237416a1 100644 --- a/salt/curator/files/curator.yml +++ b/salt/curator/files/curator.yml @@ -3,6 +3,8 @@ {% elif grains['role'] in ['so-eval', 'so-managersearch', 'so-standalone'] %} {%- set elasticsearch = salt['pillar.get']('manager:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) --- # Remember, leave a key empty if there is no value. None will be a string, @@ -11,6 +13,8 @@ client: hosts: - {{elasticsearch}} port: 9200 + username: {{ ES_USER }} + password: {{ ES_PASS }} url_prefix: use_ssl: True certificate: diff --git a/salt/elastalert/defaults.yaml b/salt/elastalert/defaults.yaml index ad675b8ee..788d87f85 100644 --- a/salt/elastalert/defaults.yaml +++ b/salt/elastalert/defaults.yaml @@ -1,3 +1,5 @@ +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) elastalert: config: rules_folder: /opt/elastalert/rules/ @@ -19,8 +21,8 @@ elastalert: use_ssl: true verify_certs: false #es_send_get_body_as: GET - #es_username: someusername - #es_password: somepassword + es_username: {{ ES_USER }} + es_password: {{ ES_PASS }} writeback_index: elastalert_status alert_time_limit: days: 2 @@ -45,4 +47,4 @@ elastalert: level: INFO handlers: - file - propagate: false \ No newline at end of file + propagate: false diff --git a/salt/filebeat/etc/filebeat.yml b/salt/filebeat/etc/filebeat.yml index 0f7c9c778..cd9c76de1 100644 --- a/salt/filebeat/etc/filebeat.yml +++ b/salt/filebeat/etc/filebeat.yml @@ -3,6 +3,8 @@ {%- else %} {%- set MANAGER = salt['grains.get']('master') %} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:pass', '') %}) {%- set HOSTNAME = salt['grains.get']('host', '') %} @@ -261,6 +263,8 @@ output.{{ type }}: output.elasticsearch: enabled: true hosts: ["https://{{ MANAGER }}:9200"] + username: "{{ ES_USER }}" + password: "{{ ES_PASS }}" ssl.certificate_authorities: ["/usr/share/filebeat/intraca.crt"] pipelines: - pipeline: "%{[module]}.%{[dataset]}" diff --git a/salt/kibana/etc/kibana.yml b/salt/kibana/etc/kibana.yml index 501d93c8a..94e170167 100644 --- a/salt/kibana/etc/kibana.yml +++ b/salt/kibana/etc/kibana.yml @@ -1,14 +1,16 @@ --- # Default Kibana configuration from kibana-docker. {%- set ES = salt['pillar.get']('manager:mainip', '') -%} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_kibana_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_kibana_user:pass', '') %}) server.name: kibana server.host: "0" server.basePath: /kibana elasticsearch.hosts: [ "https://{{ ES }}:9200" ] elasticsearch.ssl.verificationMode: none #kibana.index: ".kibana" -#elasticsearch.username: elastic -#elasticsearch.password: changeme +elasticsearch.username: {{ ES_USER }} +elasticsearch.password: {{ ES_PASS }} #xpack.monitoring.ui.container.elasticsearch.enabled: true elasticsearch.requestTimeout: 90000 logging.dest: /var/log/kibana/kibana.log @@ -19,4 +21,4 @@ xpack.security.authc.providers: anonymous.anonymous1: order: 0 credentials: "elasticsearch_anonymous_user" -{% endif %} \ No newline at end of file +{% endif %} diff --git a/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja b/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja index d17dc2b22..77f1b59ec 100644 --- a/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja +++ b/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [module] =~ "zeek" and "import" not in [tags] { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-zeek" template_name => "so-zeek" template => "/templates/so-zeek-template.json" diff --git a/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja b/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja index 4562dcee7..2453a25d8 100644 --- a/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja +++ b/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if "import" in [tags] { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-import" template_name => "so-import" template => "/templates/so-import-template.json" diff --git a/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja b/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja index fb6eaee5d..010f01ee8 100644 --- a/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja +++ b/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja @@ -3,10 +3,14 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [event_type] == "sflow" { elasticsearch { hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-flow" template_name => "so-flow" template => "/templates/so-flow-template.json" diff --git a/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja b/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja index 61aa21a82..2b42541dc 100644 --- a/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja +++ b/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja @@ -3,10 +3,14 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [event_type] == "ids" and "import" not in [tags] { elasticsearch { hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-ids" template_name => "so-ids" template => "/templates/so-ids-template.json" diff --git a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja index 0afbf45ea..b2cd7107d 100644 --- a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja +++ b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [module] =~ "syslog" { elasticsearch { pipeline => "%{module}" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-syslog" template_name => "so-syslog" template => "/templates/so-syslog-template.json" diff --git a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja index efa46c7af..d663e79b6 100644 --- a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja +++ b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_pass:pass', '') %}) output { if [module] =~ "osquery" and "live_query" not in [dataset] { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-osquery" template_name => "so-osquery" template => "/templates/so-osquery-template.json" diff --git a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja b/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja index 6d7b71415..c8e70d85a 100644 --- a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja +++ b/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja @@ -3,6 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) {% set FEATURES = salt['pillar.get']('elastic:features', False) %} filter { @@ -30,6 +32,8 @@ output { elasticsearch { pipeline => "osquery.live_query" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-osquery" template_name => "so-osquery" template => "/templates/so-osquery-template.json" diff --git a/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja b/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja index 764f597b9..2a8ab27bf 100644 --- a/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja +++ b/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja @@ -3,10 +3,14 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [dataset] =~ "firewall" { elasticsearch { hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-firewall" template_name => "so-firewall" template => "/templates/so-firewall-template.json" diff --git a/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja b/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja index 5013bafc1..de93b6c81 100644 --- a/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja +++ b/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [module] =~ "suricata" and "import" not in [tags] { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-ids" template_name => "so-ids" template => "/templates/so-ids-template.json" diff --git a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja index 349c0ada1..95dce8160 100644 --- a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja +++ b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if "beat-ext" in [tags] and "import" not in [tags] { elasticsearch { pipeline => "beats.common" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-beats" template_name => "so-beats" template => "/templates/so-beats-template.json" diff --git a/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja b/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja index 1a4987a53..ce26d6093 100644 --- a/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja +++ b/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [module] =~ "ossec" { elasticsearch { pipeline => "%{module}" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-ossec" template_name => "so-ossec" template => "/templates/so-ossec-template.json" diff --git a/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja b/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja index d564486e4..ef804ea17 100644 --- a/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja +++ b/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja @@ -3,11 +3,15 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) output { if [module] =~ "strelka" { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" + username => "{{ ES_USER }}" + password => "{{ ES_PASS }}" index => "so-strelka" template_name => "so-strelka" template => "/templates/so-strelka-template.json" diff --git a/salt/soc/files/soc/soc.json b/salt/soc/files/soc/soc.json index e275ec28b..9f274e9f8 100644 --- a/salt/soc/files/soc/soc.json +++ b/salt/soc/files/soc/soc.json @@ -18,6 +18,8 @@ {%- import_json "soc/files/soc/menu.actions.json" as menu_actions %} {%- import_json "soc/files/soc/tools.json" as tools %} {%- set DNET = salt['pillar.get']('global:dockernet', '172.17.0.0') %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) { "logFilename": "/opt/sensoroni/logs/sensoroni-server.log", @@ -47,8 +49,8 @@ {%- endfor %} ], {%- endif %} - "username": "", - "password": "", + "username": "{{ ES_USER }}", + "password": "{{ ES_PASS }}", "cacheMs": {{ ES_FIELDCAPS_CACHE }}, "verifyCert": false, "timeoutMs": {{ API_TIMEOUT }} diff --git a/salt/soctopus/files/SOCtopus.conf b/salt/soctopus/files/SOCtopus.conf index b6ee45e74..424eb35cb 100644 --- a/salt/soctopus/files/SOCtopus.conf +++ b/salt/soctopus/files/SOCtopus.conf @@ -3,13 +3,14 @@ {%- set HIVEKEY = salt['pillar.get']('global:hivekey', '') %} {%- set CORTEXKEY = salt['pillar.get']('global:cortexorguserkey', '') %} {%- set PLAYBOOK_KEY = salt['pillar.get']('playbook:api_key', '') %} - +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) [es] es_url = https://{{MANAGER}}:9200 es_ip = {{MANAGER}} -es_user = -es_pass = +es_user = {{ ES_USER }} +es_pass = {{ ES_PASS }} es_index_pattern = so-* es_verifycert = no diff --git a/salt/telegraf/etc/telegraf.conf b/salt/telegraf/etc/telegraf.conf index af3474913..8c910b718 100644 --- a/salt/telegraf/etc/telegraf.conf +++ b/salt/telegraf/etc/telegraf.conf @@ -14,6 +14,8 @@ # for numbers and booleans they should be plain (ie, $INT_VAR, $BOOL_VAR) {%- set MANAGER = salt['grains.get']('master') %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) {% set NODEIP = salt['pillar.get']('elasticsearch:mainip', '') %} {% set HELIX_API_KEY = salt['pillar.get']('fireeye:helix:api_key', '') %} {% set UNIQUEID = salt['pillar.get']('sensor:uniqueid', '') %} @@ -620,10 +622,14 @@ {% if grains['role'] in ['so-manager', 'so-eval', 'so-managersearch', 'so-standalone'] %} [[inputs.elasticsearch]] servers = ["https://{{ MANAGER }}:9200"] + username = "{{ ES_USER }}" + password = "{{ ES_PASS }}" insecure_skip_verify = true {% elif grains['role'] in ['so-node', 'so-hotnode', 'so-warmnode', 'so-heavynode'] %} [[inputs.elasticsearch]] servers = ["https://{{ NODEIP }}:9200"] + username = "{{ ES_USER }}" + password = "{{ ES_PASS }}" insecure_skip_verify = true {% endif %} From 588da4d7dcd6a41fd7975204ad7498991d88c3cc Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 2 Jun 2021 14:34:21 -0400 Subject: [PATCH 49/76] Resolve salt pillar/state/jinja race condition --- salt/elasticsearch/auth.sls | 2 ++ salt/elasticsearch/files/curl.config.template | 1 + salt/manager/init.sls | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 salt/elasticsearch/files/curl.config.template diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls index 748e50d0b..9bca61e01 100644 --- a/salt/elasticsearch/auth.sls +++ b/salt/elasticsearch/auth.sls @@ -7,6 +7,8 @@ elastic_auth_pillar: file.managed: - name: /opt/so/saltstack/local/pillar/elasticsearch/auth.sls + - mode 600 + - reload_pillar: True - contents: | elasticsearch: auth: diff --git a/salt/elasticsearch/files/curl.config.template b/salt/elasticsearch/files/curl.config.template new file mode 100644 index 000000000..14f5a2a1d --- /dev/null +++ b/salt/elasticsearch/files/curl.config.template @@ -0,0 +1 @@ +user = "{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user') }}:{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass') }}" \ No newline at end of file diff --git a/salt/manager/init.sls b/salt/manager/init.sls index 9ae39e9a8..ca47af34f 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -110,8 +110,9 @@ strelka_yara_update: elastic_curl_config_distributed: file.managed: - name: /opt/so/saltstack/local/salt/elasticsearch/curl.config + - source: salt://elasticsearch/files/curl.config.template + - template: jinja - mode: 600 - - contents: user = "{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user') }}:{{ salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass') }}" - show_changes: False # Must run before elasticsearch docker container is started! From fc6b3726a47abe865f36eccfda8a793bb8e4fdca Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 2 Jun 2021 15:23:16 -0400 Subject: [PATCH 50/76] Fix missing colon for mode --- salt/elasticsearch/auth.sls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/elasticsearch/auth.sls b/salt/elasticsearch/auth.sls index 9bca61e01..373f2fbed 100644 --- a/salt/elasticsearch/auth.sls +++ b/salt/elasticsearch/auth.sls @@ -7,7 +7,7 @@ elastic_auth_pillar: file.managed: - name: /opt/so/saltstack/local/pillar/elasticsearch/auth.sls - - mode 600 + - mode: 600 - reload_pillar: True - contents: | elasticsearch: From 901242f7e97accf48b67a70c1c61fb5069473a5e Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 2 Jun 2021 16:23:45 -0400 Subject: [PATCH 51/76] remove extra parenthesis --- salt/curator/files/curator.yml | 4 ++-- salt/elastalert/defaults.yaml | 4 ++-- salt/filebeat/etc/filebeat.yml | 4 ++-- salt/kibana/etc/kibana.yml | 4 ++-- salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja | 4 ++-- .../pipelines/config/so/9002_output_import.conf.jinja | 4 ++-- salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja | 4 ++-- .../logstash/pipelines/config/so/9033_output_snort.conf.jinja | 4 ++-- .../pipelines/config/so/9034_output_syslog.conf.jinja | 4 ++-- .../pipelines/config/so/9100_output_osquery.conf.jinja | 4 ++-- .../config/so/9101_output_osquery_livequery.conf.jinja | 4 ++-- .../pipelines/config/so/9200_output_firewall.conf.jinja | 4 ++-- .../pipelines/config/so/9400_output_suricata.conf.jinja | 4 ++-- .../logstash/pipelines/config/so/9500_output_beats.conf.jinja | 4 ++-- .../logstash/pipelines/config/so/9600_output_ossec.conf.jinja | 4 ++-- .../pipelines/config/so/9700_output_strelka.conf.jinja | 4 ++-- salt/soc/files/soc/soc.json | 4 ++-- salt/soctopus/files/SOCtopus.conf | 4 ++-- salt/telegraf/etc/telegraf.conf | 4 ++-- 19 files changed, 38 insertions(+), 38 deletions(-) diff --git a/salt/curator/files/curator.yml b/salt/curator/files/curator.yml index a237416a1..0934aaf02 100644 --- a/salt/curator/files/curator.yml +++ b/salt/curator/files/curator.yml @@ -3,8 +3,8 @@ {% elif grains['role'] in ['so-eval', 'so-managersearch', 'so-standalone'] %} {%- set elasticsearch = salt['pillar.get']('manager:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} --- # Remember, leave a key empty if there is no value. None will be a string, diff --git a/salt/elastalert/defaults.yaml b/salt/elastalert/defaults.yaml index 788d87f85..accccaa3a 100644 --- a/salt/elastalert/defaults.yaml +++ b/salt/elastalert/defaults.yaml @@ -1,5 +1,5 @@ -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} elastalert: config: rules_folder: /opt/elastalert/rules/ diff --git a/salt/filebeat/etc/filebeat.yml b/salt/filebeat/etc/filebeat.yml index cd9c76de1..9ae408654 100644 --- a/salt/filebeat/etc/filebeat.yml +++ b/salt/filebeat/etc/filebeat.yml @@ -3,8 +3,8 @@ {%- else %} {%- set MANAGER = salt['grains.get']('master') %} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:pass', '') %} {%- set HOSTNAME = salt['grains.get']('host', '') %} diff --git a/salt/kibana/etc/kibana.yml b/salt/kibana/etc/kibana.yml index 94e170167..a3f83a516 100644 --- a/salt/kibana/etc/kibana.yml +++ b/salt/kibana/etc/kibana.yml @@ -1,8 +1,8 @@ --- # Default Kibana configuration from kibana-docker. {%- set ES = salt['pillar.get']('manager:mainip', '') -%} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_kibana_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_kibana_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_kibana_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_kibana_user:pass', '') %} server.name: kibana server.host: "0" server.basePath: /kibana diff --git a/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja b/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja index 77f1b59ec..2151b5f0c 100644 --- a/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja +++ b/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [module] =~ "zeek" and "import" not in [tags] { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja b/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja index 2453a25d8..d8f888f40 100644 --- a/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja +++ b/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if "import" in [tags] { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja b/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja index 010f01ee8..5e5c95f18 100644 --- a/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja +++ b/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [event_type] == "sflow" { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja b/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja index 2b42541dc..e7fc06f8c 100644 --- a/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja +++ b/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [event_type] == "ids" and "import" not in [tags] { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja index b2cd7107d..a98c437ad 100644 --- a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja +++ b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [module] =~ "syslog" { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja index d663e79b6..aab7318a2 100644 --- a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja +++ b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_pass:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_pass:pass', '') %} output { if [module] =~ "osquery" and "live_query" not in [dataset] { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja b/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja index c8e70d85a..b6b84c771 100644 --- a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja +++ b/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} {% set FEATURES = salt['pillar.get']('elastic:features', False) %} filter { diff --git a/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja b/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja index 2a8ab27bf..cda388f8c 100644 --- a/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja +++ b/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [dataset] =~ "firewall" { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja b/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja index de93b6c81..ac71ec131 100644 --- a/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja +++ b/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [module] =~ "suricata" and "import" not in [tags] { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja index 95dce8160..21c307107 100644 --- a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja +++ b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if "beat-ext" in [tags] and "import" not in [tags] { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja b/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja index ce26d6093..b71718c8f 100644 --- a/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja +++ b/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [module] =~ "ossec" { elasticsearch { diff --git a/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja b/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja index ef804ea17..3581c061f 100644 --- a/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja +++ b/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja @@ -3,8 +3,8 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [module] =~ "strelka" { elasticsearch { diff --git a/salt/soc/files/soc/soc.json b/salt/soc/files/soc/soc.json index 9f274e9f8..2cd213276 100644 --- a/salt/soc/files/soc/soc.json +++ b/salt/soc/files/soc/soc.json @@ -18,8 +18,8 @@ {%- import_json "soc/files/soc/menu.actions.json" as menu_actions %} {%- import_json "soc/files/soc/tools.json" as tools %} {%- set DNET = salt['pillar.get']('global:dockernet', '172.17.0.0') %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} { "logFilename": "/opt/sensoroni/logs/sensoroni-server.log", diff --git a/salt/soctopus/files/SOCtopus.conf b/salt/soctopus/files/SOCtopus.conf index 424eb35cb..4b47c8b6a 100644 --- a/salt/soctopus/files/SOCtopus.conf +++ b/salt/soctopus/files/SOCtopus.conf @@ -3,8 +3,8 @@ {%- set HIVEKEY = salt['pillar.get']('global:hivekey', '') %} {%- set CORTEXKEY = salt['pillar.get']('global:cortexorguserkey', '') %} {%- set PLAYBOOK_KEY = salt['pillar.get']('playbook:api_key', '') %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} [es] es_url = https://{{MANAGER}}:9200 diff --git a/salt/telegraf/etc/telegraf.conf b/salt/telegraf/etc/telegraf.conf index 8c910b718..659a78398 100644 --- a/salt/telegraf/etc/telegraf.conf +++ b/salt/telegraf/etc/telegraf.conf @@ -14,8 +14,8 @@ # for numbers and booleans they should be plain (ie, $INT_VAR, $BOOL_VAR) {%- set MANAGER = salt['grains.get']('master') %} -{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}) -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}) +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} {% set NODEIP = salt['pillar.get']('elasticsearch:mainip', '') %} {% set HELIX_API_KEY = salt['pillar.get']('fireeye:helix:api_key', '') %} {% set UNIQUEID = salt['pillar.get']('sensor:uniqueid', '') %} From fa6af06204a8a71e7607566f35399b2f81624201 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 2 Jun 2021 17:13:59 -0400 Subject: [PATCH 52/76] Avoid running highstate during setup when flipping auth flag --- salt/common/tools/sbin/so-elastic-auth | 12 ++++++++---- setup/so-setup | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/salt/common/tools/sbin/so-elastic-auth b/salt/common/tools/sbin/so-elastic-auth index b15b04c0f..d4b8057a3 100644 --- a/salt/common/tools/sbin/so-elastic-auth +++ b/salt/common/tools/sbin/so-elastic-auth @@ -30,8 +30,10 @@ fi if [[ "$authEnable" == "true" ]]; then if grep -q "enabled: False" "$ES_AUTH_PILLAR"; then sed -i 's/enabled: False/enabled: True/g' "$ES_AUTH_PILLAR" - echo "Applying highstate - this may take a few minutes..." - salt-call state.highstate queue=True + if [[ -z "$ELASTIC_AUTH_SKIP_HIGHSTATE" ]]; then + echo "Applying highstate - this may take a few minutes..." + salt-call state.highstate queue=True + fi echo "Elastic auth is now enabled." if grep -q "argon" "$ES_USERS_FILE"; then echo "" @@ -44,8 +46,10 @@ if [[ "$authEnable" == "true" ]]; then elif [[ "$authEnable" == "false" ]]; then if grep -q "enabled: True" "$ES_AUTH_PILLAR"; then sed -i 's/enabled: True/enabled: False/g' "$ES_AUTH_PILLAR" - echo "Applying highstate - this may take a few minutes..." - salt-call state.highstate queue=True + if [[ -z "$ELASTIC_AUTH_SKIP_HIGHSTATE" ]]; then + echo "Applying highstate - this may take a few minutes..." + salt-call state.highstate queue=True + fi echo "Elastic auth is now disabled." else echo "Auth is already disabled." diff --git a/setup/so-setup b/setup/so-setup index 6d2f6ac27..ed6899db8 100755 --- a/setup/so-setup +++ b/setup/so-setup @@ -752,7 +752,7 @@ echo "1" > /root/accept_changes set_progress_str 60 "$(print_salt_state_apply 'manager')" salt-call state.apply -l info manager >> $setup_log 2>&1 - bash /opt/so/saltstack/default/salt/common/tools/sbin/so-elastic-auth + ELASTIC_AUTH_SKIP_HIGHSTATE=true bash /opt/so/saltstack/default/salt/common/tools/sbin/so-elastic-auth fi set_progress_str 61 "$(print_salt_state_apply 'firewall')" From e6165f0046c3963a5fdd19741b91b0a4cda2b675 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Thu, 3 Jun 2021 07:47:32 -0400 Subject: [PATCH 53/76] Update kibana config load for auth changes --- salt/kibana/bin/so-kibana-config-load | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/salt/kibana/bin/so-kibana-config-load b/salt/kibana/bin/so-kibana-config-load index 8f80b5c3d..fb50d0cf9 100644 --- a/salt/kibana/bin/so-kibana-config-load +++ b/salt/kibana/bin/so-kibana-config-load @@ -1,6 +1,4 @@ #!/bin/bash -# {%- set FLEET_MANAGER = salt['pillar.get']('global:fleet_manager', False) -%} -# {%- set FLEET_NODE = salt['pillar.get']('global:fleet_node', False) -%} # {%- set MANAGER = salt['pillar.get']('global:url_base', '') %} . /usr/sbin/so-common @@ -8,19 +6,10 @@ # Copy template file cp /opt/so/conf/kibana/saved_objects.ndjson.template /opt/so/conf/kibana/saved_objects.ndjson -# {% if FLEET_NODE or FLEET_MANAGER %} -# Fleet IP -#sed -i "s/FLEETPLACEHOLDER/{{ MANAGER }}/g" /opt/so/conf/kibana/saved_objects.ndjson -# {% endif %} - # SOCtopus and Manager sed -i "s/PLACEHOLDER/{{ MANAGER }}/g" /opt/so/conf/kibana/saved_objects.ndjson -#wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}" -## This hackery will be removed if using Elastic Auth ## - -# Let's snag a cookie from Kibana -THECOOKIE=$({{ ELASTICCURL }} -c - -X GET http://localhost:5601/ | grep sid | awk '{print $7}') +wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 {{ ELASTICCURL }} # Load saved objects -{{ ELASTICCURL }} -b "sid=$THECOOKIE" -L -X POST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "kbn-xsrf: true" --form file=@/opt/so/conf/kibana/saved_objects.ndjson >> /opt/so/log/kibana/misc.log +curl -L -X POST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "kbn-xsrf: true" --form file=@/opt/so/conf/kibana/saved_objects.ndjson >> /opt/so/log/kibana/misc.log From 5c527b2c486686f090c3d73a5bdab27914cb7df1 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Thu, 3 Jun 2021 07:51:43 -0400 Subject: [PATCH 54/76] Rename username param to user since logstash is 'unique' --- salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja | 2 +- salt/logstash/pipelines/config/so/9002_output_import.conf.jinja | 2 +- salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja | 2 +- salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja | 2 +- salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja | 2 +- .../logstash/pipelines/config/so/9100_output_osquery.conf.jinja | 2 +- .../config/so/9101_output_osquery_livequery.conf.jinja | 2 +- .../pipelines/config/so/9200_output_firewall.conf.jinja | 2 +- .../pipelines/config/so/9400_output_suricata.conf.jinja | 2 +- salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja | 2 +- salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja | 2 +- .../logstash/pipelines/config/so/9700_output_strelka.conf.jinja | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja b/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja index 2151b5f0c..af3a9f93b 100644 --- a/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja +++ b/salt/logstash/pipelines/config/so/9000_output_zeek.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-zeek" template_name => "so-zeek" diff --git a/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja b/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja index d8f888f40..feaddeded 100644 --- a/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja +++ b/salt/logstash/pipelines/config/so/9002_output_import.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-import" template_name => "so-import" diff --git a/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja b/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja index 5e5c95f18..e01792914 100644 --- a/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja +++ b/salt/logstash/pipelines/config/so/9004_output_flow.conf.jinja @@ -9,7 +9,7 @@ output { if [event_type] == "sflow" { elasticsearch { hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-flow" template_name => "so-flow" diff --git a/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja b/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja index e7fc06f8c..42e4dbee4 100644 --- a/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja +++ b/salt/logstash/pipelines/config/so/9033_output_snort.conf.jinja @@ -9,7 +9,7 @@ output { if [event_type] == "ids" and "import" not in [tags] { elasticsearch { hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-ids" template_name => "so-ids" diff --git a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja index a98c437ad..ca6308ada 100644 --- a/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja +++ b/salt/logstash/pipelines/config/so/9034_output_syslog.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "%{module}" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-syslog" template_name => "so-syslog" diff --git a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja index aab7318a2..7ed8c58e5 100644 --- a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja +++ b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-osquery" template_name => "so-osquery" diff --git a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja b/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja index b6b84c771..10c3cba9f 100644 --- a/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja +++ b/salt/logstash/pipelines/config/so/9101_output_osquery_livequery.conf.jinja @@ -32,7 +32,7 @@ output { elasticsearch { pipeline => "osquery.live_query" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-osquery" template_name => "so-osquery" diff --git a/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja b/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja index cda388f8c..6abe75f9d 100644 --- a/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja +++ b/salt/logstash/pipelines/config/so/9200_output_firewall.conf.jinja @@ -9,7 +9,7 @@ output { if [dataset] =~ "firewall" { elasticsearch { hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-firewall" template_name => "so-firewall" diff --git a/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja b/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja index ac71ec131..62b713f0f 100644 --- a/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja +++ b/salt/logstash/pipelines/config/so/9400_output_suricata.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-ids" template_name => "so-ids" diff --git a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja index 21c307107..ffe30c8c5 100644 --- a/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja +++ b/salt/logstash/pipelines/config/so/9500_output_beats.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "beats.common" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-beats" template_name => "so-beats" diff --git a/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja b/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja index b71718c8f..7ef4bca1f 100644 --- a/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja +++ b/salt/logstash/pipelines/config/so/9600_output_ossec.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "%{module}" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-ossec" template_name => "so-ossec" diff --git a/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja b/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja index 3581c061f..a26373397 100644 --- a/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja +++ b/salt/logstash/pipelines/config/so/9700_output_strelka.conf.jinja @@ -10,7 +10,7 @@ output { elasticsearch { pipeline => "%{module}.%{dataset}" hosts => "{{ ES }}" - username => "{{ ES_USER }}" + user => "{{ ES_USER }}" password => "{{ ES_PASS }}" index => "so-strelka" template_name => "so-strelka" From 2af43d62ebda24ce4a992539c383cc76153280f6 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Thu, 3 Jun 2021 08:53:59 -0400 Subject: [PATCH 55/76] Wrap curl param in quotes for function call --- salt/kibana/bin/so-kibana-config-load | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/kibana/bin/so-kibana-config-load b/salt/kibana/bin/so-kibana-config-load index fb50d0cf9..00dc7f9ff 100644 --- a/salt/kibana/bin/so-kibana-config-load +++ b/salt/kibana/bin/so-kibana-config-load @@ -9,7 +9,7 @@ cp /opt/so/conf/kibana/saved_objects.ndjson.template /opt/so/conf/kibana/saved_o # SOCtopus and Manager sed -i "s/PLACEHOLDER/{{ MANAGER }}/g" /opt/so/conf/kibana/saved_objects.ndjson -wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 {{ ELASTICCURL }} +wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}" # Load saved objects curl -L -X POST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "kbn-xsrf: true" --form file=@/opt/so/conf/kibana/saved_objects.ndjson >> /opt/so/log/kibana/misc.log From 58ae3479dcd76bf6ec46de4e89370de97fb5676a Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Thu, 3 Jun 2021 10:11:10 -0400 Subject: [PATCH 56/76] Fix mispelled db filename; ensure ELASTICCURL is used for loading config objects --- salt/kibana/bin/so-kibana-config-load | 2 +- salt/manager/files/beacons.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/kibana/bin/so-kibana-config-load b/salt/kibana/bin/so-kibana-config-load index 00dc7f9ff..0bbcba375 100644 --- a/salt/kibana/bin/so-kibana-config-load +++ b/salt/kibana/bin/so-kibana-config-load @@ -12,4 +12,4 @@ sed -i "s/PLACEHOLDER/{{ MANAGER }}/g" /opt/so/conf/kibana/saved_objects.ndjson wait_for_web_response "http://localhost:5601/app/kibana" "Elastic" 300 "{{ ELASTICCURL }}" # Load saved objects -curl -L -X POST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "kbn-xsrf: true" --form file=@/opt/so/conf/kibana/saved_objects.ndjson >> /opt/so/log/kibana/misc.log +{{ ELASTICCURL }} -L -X POST "localhost:5601/api/saved_objects/_import?overwrite=true" -H "kbn-xsrf: true" --form file=@/opt/so/conf/kibana/saved_objects.ndjson >> /opt/so/log/kibana/misc.log diff --git a/salt/manager/files/beacons.conf b/salt/manager/files/beacons.conf index c40fe83cb..fe40170ad 100644 --- a/salt/manager/files/beacons.conf +++ b/salt/manager/files/beacons.conf @@ -1,7 +1,7 @@ beacons: watch_sqlite_db: - files: - /opt/so/conf/kratos/db/sqlite.db: + /opt/so/conf/kratos/db/db.sqlite: mask: - modify - beacon_module: inotify From 316035910f02e361d0c679b42bca98896c443cff Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Thu, 3 Jun 2021 15:15:35 -0400 Subject: [PATCH 57/76] Remove inotify beacon due to it not functioning as documented; Add back so-user changes to sync upon so-user changes --- salt/common/tools/sbin/so-user | 5 +++++ salt/manager/files/beacons.conf | 7 ------- salt/manager/init.sls | 7 ------- 3 files changed, 5 insertions(+), 14 deletions(-) delete mode 100644 salt/manager/files/beacons.conf diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 15a71edfa..f1bfdc213 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -314,6 +314,7 @@ case "${operation}" in validateEmail "$email" updatePassword createUser "$email" + syncAll echo "Successfully added new user to SOC" check_container thehive && echo $password | so-thehive-user-add "$email" check_container fleet && echo $password | so-fleet-user-add "$email" @@ -329,6 +330,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateUser "$email" + syncAll echo "Successfully updated user" ;; @@ -337,6 +339,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'active' + syncAll echo "Successfully enabled user" check_container thehive && so-thehive-user-enable "$email" true check_container fleet && so-fleet-user-enable "$email" true @@ -347,6 +350,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" updateStatus "$email" 'locked' + syncAll echo "Successfully disabled user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false @@ -357,6 +361,7 @@ case "${operation}" in [[ "$email" == "" ]] && fail "Email address must be provided" deleteUser "$email" + syncAll echo "Successfully deleted user" check_container thehive && so-thehive-user-enable "$email" false check_container fleet && so-fleet-user-enable "$email" false diff --git a/salt/manager/files/beacons.conf b/salt/manager/files/beacons.conf deleted file mode 100644 index fe40170ad..000000000 --- a/salt/manager/files/beacons.conf +++ /dev/null @@ -1,7 +0,0 @@ -beacons: - watch_sqlite_db: - - files: - /opt/so/conf/kratos/db/db.sqlite: - mask: - - modify - - beacon_module: inotify diff --git a/salt/manager/init.sls b/salt/manager/init.sls index ca47af34f..e6e9c433b 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -123,13 +123,6 @@ syncesusers: - /opt/so/saltstack/local/salt/elasticsearch/files/users - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles -beacons_config: - file.managed: - - name: /etc/salt/minion.d/beacons.conf - - source: salt://manager/files/beacons.conf - - onchanges_in: - - service: salt_minion_service - {% else %} {{sls}}_state_not_allowed: From 416b38fc71714701e50b99ab28368cf494429d97 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 4 Jun 2021 11:24:58 -0400 Subject: [PATCH 58/76] Use cronjob to ensure user synchronization --- salt/common/tools/sbin/so-user | 10 ++++++++-- salt/soc/init.sls | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index f1bfdc213..4a7b6f0da 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -220,6 +220,13 @@ function syncElastic() { } function syncAll() { + if [[ -n "$STALE_MIN" ]]; then + staleCount=$(echo "select from identity_credentials where updated_at >= Datetime('now', '-${STALE_MIN} minutes');" \ + | sqlite3 "$databasePath") + if [[ "$staleCount" == "0" ]]; then + return 1 + fi + fi syncElastic } @@ -368,8 +375,7 @@ case "${operation}" in ;; "sync") - syncAll - echo "Synchronization complete" + syncAll && echo "Synchronization completed at $(date)" ;; "validate") diff --git a/salt/soc/init.sls b/salt/soc/init.sls index 18fda41da..5fe403934 100644 --- a/salt/soc/init.sls +++ b/salt/soc/init.sls @@ -62,6 +62,11 @@ soccustom: - mode: 600 - template: jinja +sosyncusers: + cron.present: + - user: root + - name: 'STALE_MIN=1 /usr/sbin/so-user sync &>> /opt/so/log/soc/sync.log' + so-soc: docker_container.running: - image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-soc:{{ VERSION }} From e22421ec99f39ea5babbfac76a3bb53c35d19f79 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 4 Jun 2021 20:01:30 -0400 Subject: [PATCH 59/76] Refactor users/roles management via salt due to Salt's clobbering of the inode which breaks Docker mounts --- salt/common/tools/sbin/so-user | 47 +++++++++---------- salt/elasticsearch/init.sls | 20 +++++++- .../config/so/9100_output_osquery.conf.jinja | 2 +- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 4a7b6f0da..877f245c8 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -129,13 +129,12 @@ function updatePassword() { fi } -function createElasticTmpFile() { +function createElasticFile() { filename=$1 - tmpFile=${filename}.tmp + tmpFile=${filename} truncate -s 0 "$tmpFile" chmod 600 "$tmpFile" chown "${esUID}:${esGID}" "$tmpFile" - echo "$tmpFile" } function syncElasticSystemUser() { @@ -166,26 +165,27 @@ function syncElasticSystemRole() { } function syncElastic() { - usersFileTmp=$(createElasticTmpFile "${elasticUsersFile}") - rolesFileTmp=$(createElasticTmpFile "${elasticRolesFile}") + createElasticFile "${elasticUsersFile}" + createElasticFile "${elasticRolesFile}" authPillarJson=$(lookup_salt_value "auth" "elasticsearch" "pillar" "json") - syncElasticSystemUser "$authPillarJson" "so_elastic_user" "$usersFileTmp" - syncElasticSystemRole "$authPillarJson" "so_elastic_user" "superuser" "$rolesFileTmp" + syncElasticSystemUser "$authPillarJson" "so_elastic_user" "$elasticUsersFile" + syncElasticSystemRole "$authPillarJson" "so_elastic_user" "superuser" "$elasticRolesFile" - syncElasticSystemUser "$authPillarJson" "so_kibana_user" "$usersFileTmp" - syncElasticSystemRole "$authPillarJson" "so_kibana_user" "kibana_system" "$rolesFileTmp" + syncElasticSystemUser "$authPillarJson" "so_kibana_user" "$elasticUsersFile" + syncElasticSystemRole "$authPillarJson" "so_kibana_user" "superuser" "$elasticRolesFile" - syncElasticSystemUser "$authPillarJson" "so_logstash_user" "$usersFileTmp" - syncElasticSystemRole "$authPillarJson" "so_logstash_user" "logstash_system" "$rolesFileTmp" + syncElasticSystemUser "$authPillarJson" "so_logstash_user" "$elasticUsersFile" + syncElasticSystemRole "$authPillarJson" "so_logstash_user" "superuser" "$elasticRolesFile" - syncElasticSystemUser "$authPillarJson" "so_beats_user" "$usersFileTmp" - syncElasticSystemRole "$authPillarJson" "so_beats_user" "beats_system" "$rolesFileTmp" + syncElasticSystemUser "$authPillarJson" "so_beats_user" "$elasticUsersFile" + syncElasticSystemRole "$authPillarJson" "so_beats_user" "superuser" "$elasticRolesFile" - syncElasticSystemUser "$authPillarJson" "so_monitor_user" "$usersFileTmp" - syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_collector" "$rolesFileTmp" - syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_agent" "$rolesFileTmp" + syncElasticSystemUser "$authPillarJson" "so_monitor_user" "$elasticUsersFile" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_collector" "$elasticRolesFile" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_agent" "$elasticRolesFile" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "monitoring_user" "$elasticRolesFile" if [[ -f "$databasePath" ]]; then # Generate the new users file @@ -195,7 +195,7 @@ function syncElastic() { "order by ici.identifier;" | \ sqlite3 "$databasePath" | \ jq -r '.user + ":" + .data.hashed_password' \ - >> "$usersFileTmp" + >> "$elasticUsersFile" [[ $? != 0 ]] && fail "Unable to read credential hashes from database" # Generate the new users_roles file @@ -205,29 +205,26 @@ function syncElastic() { "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ "order by ici.identifier;" | \ sqlite3 "$databasePath" \ - >> "$rolesFileTmp" + >> "$elasticRolesFile" [[ $? != 0 ]] && fail "Unable to read credential IDs from database" else echo "Database file does not exist yet, skipping users export" fi - # Move the temp files over onto the final files - mv -f "$usersFileTmp" "$elasticUsersFile" - [[ $? != 0 ]] && fail "Unable to create users file: $elasticUsersFile" - - mv -f "$rolesFileTmp" "$elasticRolesFile" - [[ $? != 0 ]] && fail "Unable to create users file: $elasticRolesFile" + echo "Applying elastic state..." + salt-call state.apply elasticsearch queue=True } function syncAll() { if [[ -n "$STALE_MIN" ]]; then - staleCount=$(echo "select from identity_credentials where updated_at >= Datetime('now', '-${STALE_MIN} minutes');" \ + staleCount=$(echo "select count(*) from identity_credentials where updated_at >= Datetime('now', '-${STALE_MIN} minutes');" \ | sqlite3 "$databasePath") if [[ "$staleCount" == "0" ]]; then return 1 fi fi syncElastic + return 0 } function listUsers() { diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 0bf442587..05b58b79a 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -173,7 +173,7 @@ eslogdir: auth_users: file.managed: - - name: /opt/so/conf/elasticsearch/users + - name: /opt/so/conf/elasticsearch/users.tmp - source: salt://elasticsearch/files/users - user: 930 - group: 930 @@ -181,12 +181,28 @@ auth_users: auth_users_roles: file.managed: - - name: /opt/so/conf/elasticsearch/users_roles + - name: /opt/so/conf/elasticsearch/users_roles.tmp - source: salt://elasticsearch/files/users_roles - user: 930 - group: 930 - mode: 600 +auth_users_inode: + require: + - file: auth_users + cmd.run: + - name: cat /opt/so/conf/elasticsearch/users.tmp > /opt/so/conf/elasticsearch/users && chown 930:930 /opt/so/conf/elasticsearch/users && chmod 600 /opt/so/conf/elasticsearch/users + - onchanges: + - file: /opt/so/conf/elasticsearch/users.tmp + +auth_users_roles_inode: + require: + - file: auth_users_roles + cmd.run: + - name: cat /opt/so/conf/elasticsearch/users_roles.tmp > /opt/so/conf/elasticsearch/users_roles && chown 930:930 /opt/so/conf/elasticsearch/users_roles && chmod 600 /opt/so/conf/elasticsearch/users_roles + - onchanges: + - file: /opt/so/conf/elasticsearch/users_roles.tmp + so-elasticsearch: docker_container.running: - image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-elasticsearch:{{ VERSION }} diff --git a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja index 7ed8c58e5..43596c1cd 100644 --- a/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja +++ b/salt/logstash/pipelines/config/so/9100_output_osquery.conf.jinja @@ -4,7 +4,7 @@ {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} {%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} -{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_pass:pass', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { if [module] =~ "osquery" and "live_query" not in [dataset] { elasticsearch { From ba29b5e0362c471ac5e00a89f89083bc9d72f09b Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Fri, 4 Jun 2021 21:56:41 -0400 Subject: [PATCH 60/76] Do not apply salt state if already applying a state --- salt/common/tools/sbin/so-user | 6 ++++-- salt/manager/init.sls | 2 ++ salt/reactor/kratos.sls | 5 ----- 3 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 salt/reactor/kratos.sls diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 877f245c8..9873764d9 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -211,8 +211,10 @@ function syncElastic() { echo "Database file does not exist yet, skipping users export" fi - echo "Applying elastic state..." - salt-call state.apply elasticsearch queue=True + if [[ -z "$SKIP_STATE_APPLY" ]]; then + echo "Applying elastic state..." + salt-call state.apply elasticsearch queue=True + fi } function syncAll() { diff --git a/salt/manager/init.sls b/salt/manager/init.sls index e6e9c433b..0b54fbc2f 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -119,6 +119,8 @@ elastic_curl_config_distributed: syncesusers: cmd.run: - name: so-user sync + - env: + - SKIP_STATE_APPLY: 'true' - creates: - /opt/so/saltstack/local/salt/elasticsearch/files/users - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles diff --git a/salt/reactor/kratos.sls b/salt/reactor/kratos.sls deleted file mode 100644 index fb90cc164..000000000 --- a/salt/reactor/kratos.sls +++ /dev/null @@ -1,5 +0,0 @@ -so_user_sync: - local.cmd.run: - - tgt: {{ data['data']['id'] }} - - arg: - - /usr/sbin/so-user sync From 84141082abc86080356617dc02b6aa564a541132 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Sat, 5 Jun 2021 08:41:48 -0400 Subject: [PATCH 61/76] Avoid applying state when adding web user --- setup/so-functions | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup/so-functions b/setup/so-functions index 33e0514fc..426406c78 100755 --- a/setup/so-functions +++ b/setup/so-functions @@ -120,7 +120,9 @@ add_web_user() { wait_for_file /opt/so/conf/kratos/db/db.sqlite 30 5 { echo "Attempting to add administrator user for web interface..."; + export SKIP_STATE_APPLY=true echo "$WEBPASSWD1" | /usr/sbin/so-user add "$WEBUSER"; + unset SKIP_STATE_APPLY echo "Add user result: $?"; } >> "/root/so-user-add.log" 2>&1 } From 11b2b2a893e23b99eb227cef575026a23a0026a7 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Sun, 6 Jun 2021 05:42:34 -0400 Subject: [PATCH 62/76] Switch ownership of curl config to socore --- salt/manager/init.sls | 2 ++ 1 file changed, 2 insertions(+) diff --git a/salt/manager/init.sls b/salt/manager/init.sls index 0b54fbc2f..b45ffdf46 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -113,6 +113,8 @@ elastic_curl_config_distributed: - source: salt://elasticsearch/files/curl.config.template - template: jinja - mode: 600 + - user: 939 + - group: 939 - show_changes: False # Must run before elasticsearch docker container is started! From bebba7d280d39b91ccc177e3934aafffa6111d56 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Sun, 6 Jun 2021 07:43:53 -0400 Subject: [PATCH 63/76] Switch ownership of curl config to socore --- salt/common/init.sls | 2 ++ salt/manager/init.sls | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/common/init.sls b/salt/common/init.sls index 9d20de62b..25e8a62cb 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -173,6 +173,8 @@ elastic_curl_config: - name: /opt/so/conf/elasticsearch/curl.config - source: salt://elasticsearch/curl.config - mode: 600 + - user: 939 + - group: 939 - show_changes: False - makedirs: True diff --git a/salt/manager/init.sls b/salt/manager/init.sls index b45ffdf46..0b54fbc2f 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -113,8 +113,6 @@ elastic_curl_config_distributed: - source: salt://elasticsearch/files/curl.config.template - template: jinja - mode: 600 - - user: 939 - - group: 939 - show_changes: False # Must run before elasticsearch docker container is started! From fdab17a3b9adc8ce16e86ee7965196248144af9c Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Sun, 6 Jun 2021 16:36:35 -0400 Subject: [PATCH 64/76] Due to dir ownership restrictions need to run crossthestreams and eval as root --- salt/common/init.sls | 2 -- salt/utility/init.sls | 2 -- 2 files changed, 4 deletions(-) diff --git a/salt/common/init.sls b/salt/common/init.sls index 25e8a62cb..9d20de62b 100644 --- a/salt/common/init.sls +++ b/salt/common/init.sls @@ -173,8 +173,6 @@ elastic_curl_config: - name: /opt/so/conf/elasticsearch/curl.config - source: salt://elasticsearch/curl.config - mode: 600 - - user: 939 - - group: 939 - show_changes: False - makedirs: True diff --git a/salt/utility/init.sls b/salt/utility/init.sls index 0b4f0f2c3..1ff69ae71 100644 --- a/salt/utility/init.sls +++ b/salt/utility/init.sls @@ -10,7 +10,6 @@ crossclusterson: cmd.script: - shell: /bin/bash - cwd: /opt/so - - runas: socore - source: salt://utility/bin/crossthestreams - template: jinja - defaults: @@ -22,7 +21,6 @@ fixsearch: cmd.script: - shell: /bin/bash - cwd: /opt/so - - runas: socore - source: salt://utility/bin/eval - template: jinja - defaults: From 14aa9805b443652a17bd747f0df8307379273575 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Sun, 6 Jun 2021 18:20:57 -0400 Subject: [PATCH 65/76] Stop failing an install because salt is already running when a highstate is applied at 95% --- setup/so-setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/so-setup b/setup/so-setup index ed6899db8..f2db4d84e 100755 --- a/setup/so-setup +++ b/setup/so-setup @@ -918,7 +918,7 @@ echo "1" > /root/accept_changes checkin_at_boot >> $setup_log 2>&1 set_progress_str 95 'Verifying setup' - salt-call -l info state.highstate >> $setup_log 2>&1 + salt-call -l info state.highstate queue=True >> $setup_log 2>&1 } | progress From e53f2217ecc26316d462685f301f36f760888c58 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 7 Jun 2021 17:24:22 -0400 Subject: [PATCH 66/76] Add so-elasticsearch-query tool --- salt/common/tools/sbin/so-elasticsearch-query | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 salt/common/tools/sbin/so-elasticsearch-query diff --git a/salt/common/tools/sbin/so-elasticsearch-query b/salt/common/tools/sbin/so-elasticsearch-query new file mode 100644 index 000000000..ffae93a0d --- /dev/null +++ b/salt/common/tools/sbin/so-elasticsearch-query @@ -0,0 +1,37 @@ +#!/bin/bash +# +# Copyright 2014,2015,2016,2017,2018,2019,2020,2021 Security Onion Solutions, LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +. /usr/sbin/so-common + +if [[ $# -lt 1 ]]; then + echo "Submit a cURL request to the local Security Onion Elasticsearch host." + echo "" + echo "Usage: $0 [ARGS,...]" + echo "" + echo "Where " + echo " PATH represents the elastic function being requested." + echo " ARGS is used to specify additional, optional curl parameters." + echo "" + echo "Examples:" + echo " $0 / | jq" + echo " $0 '*:so-*/_search' -d '{\"query\": {\"match_all\": {}},\"size\": 1}' | jq" + exit 1 +fi + +PATH=$1 +shift + +{{ ELASTICCURL }} -s -k -L -H "Content-Type: application/json" "https://localhost:9200/${PATH}" "$@" From 343c47d67abdc73cd1fd94b50d76d36c09bed36a Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 7 Jun 2021 17:26:07 -0400 Subject: [PATCH 67/76] Add so-elasticsearch-query tool --- salt/common/tools/sbin/so-elasticsearch-query | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/common/tools/sbin/so-elasticsearch-query b/salt/common/tools/sbin/so-elasticsearch-query index ffae93a0d..c56f5671f 100644 --- a/salt/common/tools/sbin/so-elasticsearch-query +++ b/salt/common/tools/sbin/so-elasticsearch-query @@ -26,7 +26,7 @@ if [[ $# -lt 1 ]]; then echo " ARGS is used to specify additional, optional curl parameters." echo "" echo "Examples:" - echo " $0 / | jq" + echo " $0 /" echo " $0 '*:so-*/_search' -d '{\"query\": {\"match_all\": {}},\"size\": 1}' | jq" exit 1 fi From d2381b0209cf994f26431344dbb3dca5cbad9343 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Tue, 8 Jun 2021 11:03:56 -0400 Subject: [PATCH 68/76] Ensure empty/aborted users/roles files do not get copied onto final filenames --- salt/common/tools/sbin/so-user | 47 ++++++++++++++++++++-------------- salt/manager/init.sls | 1 + 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 9873764d9..d21ecc58c 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -165,27 +165,29 @@ function syncElasticSystemRole() { } function syncElastic() { - createElasticFile "${elasticUsersFile}" - createElasticFile "${elasticRolesFile}" + usersTmpFile="${elasticUsersFile}.tmp" + rolesTmpFile="${elasticRolesFile}.tmp" + createElasticFile "${usersTmpFile}" + createElasticFile "${rolesTmpFile}" authPillarJson=$(lookup_salt_value "auth" "elasticsearch" "pillar" "json") - syncElasticSystemUser "$authPillarJson" "so_elastic_user" "$elasticUsersFile" - syncElasticSystemRole "$authPillarJson" "so_elastic_user" "superuser" "$elasticRolesFile" + syncElasticSystemUser "$authPillarJson" "so_elastic_user" "$usersTmpFile" + syncElasticSystemRole "$authPillarJson" "so_elastic_user" "superuser" "$rolesTmpFile" - syncElasticSystemUser "$authPillarJson" "so_kibana_user" "$elasticUsersFile" - syncElasticSystemRole "$authPillarJson" "so_kibana_user" "superuser" "$elasticRolesFile" + syncElasticSystemUser "$authPillarJson" "so_kibana_user" "$usersTmpFile" + syncElasticSystemRole "$authPillarJson" "so_kibana_user" "superuser" "$rolesTmpFile" - syncElasticSystemUser "$authPillarJson" "so_logstash_user" "$elasticUsersFile" - syncElasticSystemRole "$authPillarJson" "so_logstash_user" "superuser" "$elasticRolesFile" + syncElasticSystemUser "$authPillarJson" "so_logstash_user" "$usersTmpFile" + syncElasticSystemRole "$authPillarJson" "so_logstash_user" "superuser" "$rolesTmpFile" - syncElasticSystemUser "$authPillarJson" "so_beats_user" "$elasticUsersFile" - syncElasticSystemRole "$authPillarJson" "so_beats_user" "superuser" "$elasticRolesFile" + syncElasticSystemUser "$authPillarJson" "so_beats_user" "$usersTmpFile" + syncElasticSystemRole "$authPillarJson" "so_beats_user" "superuser" "$rolesTmpFile" - syncElasticSystemUser "$authPillarJson" "so_monitor_user" "$elasticUsersFile" - syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_collector" "$elasticRolesFile" - syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_agent" "$elasticRolesFile" - syncElasticSystemRole "$authPillarJson" "so_monitor_user" "monitoring_user" "$elasticRolesFile" + syncElasticSystemUser "$authPillarJson" "so_monitor_user" "$usersTmpFile" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_collector" "$rolesTmpFile" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "remote_monitoring_agent" "$rolesTmpFile" + syncElasticSystemRole "$authPillarJson" "so_monitor_user" "monitoring_user" "$rolesTmpFile" if [[ -f "$databasePath" ]]; then # Generate the new users file @@ -195,7 +197,7 @@ function syncElastic() { "order by ici.identifier;" | \ sqlite3 "$databasePath" | \ jq -r '.user + ":" + .data.hashed_password' \ - >> "$elasticUsersFile" + >> "$usersTmpFile" [[ $? != 0 ]] && fail "Unable to read credential hashes from database" # Generate the new users_roles file @@ -205,15 +207,22 @@ function syncElastic() { "where ici.identity_credential_id=ic.id and ic.config like '%hashed_password%' " \ "order by ici.identifier;" | \ sqlite3 "$databasePath" \ - >> "$elasticRolesFile" + >> "$rolesTmpFile" [[ $? != 0 ]] && fail "Unable to read credential IDs from database" else echo "Database file does not exist yet, skipping users export" fi - if [[ -z "$SKIP_STATE_APPLY" ]]; then - echo "Applying elastic state..." - salt-call state.apply elasticsearch queue=True + if [[ -s "${usersTmpFile}" ]]; then + mv "${usersTmpFile}" "${elasticUsersFile}" + mv "${rolesTmpFile}" "${elasticRolesFile}" + + if [[ -z "$SKIP_STATE_APPLY" ]]; then + echo "Applying elastic state..." + salt-call state.apply elasticsearch queue=True + fi + else + echo "Generated users/roles files are incomplete; aborting." fi } diff --git a/salt/manager/init.sls b/salt/manager/init.sls index 0b54fbc2f..17b1ad9e0 100644 --- a/salt/manager/init.sls +++ b/salt/manager/init.sls @@ -124,6 +124,7 @@ syncesusers: - creates: - /opt/so/saltstack/local/salt/elasticsearch/files/users - /opt/so/saltstack/local/salt/elasticsearch/files/users_roles + - show_changes: False {% else %} From dd73ad544cbfa811cbc8dacf83a5fec1144310e0 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 9 Jun 2021 09:06:29 -0400 Subject: [PATCH 69/76] Rename PATH var to avoid collision with OS PATH var; wrapped password var in quotes to support spaces in Fleet/TheHive passwords --- salt/common/tools/sbin/so-elasticsearch-query | 4 ++-- salt/common/tools/sbin/so-user | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/salt/common/tools/sbin/so-elasticsearch-query b/salt/common/tools/sbin/so-elasticsearch-query index c56f5671f..80dd6ee2e 100644 --- a/salt/common/tools/sbin/so-elasticsearch-query +++ b/salt/common/tools/sbin/so-elasticsearch-query @@ -31,7 +31,7 @@ if [[ $# -lt 1 ]]; then exit 1 fi -PATH=$1 +QUERYPATH=$1 shift -{{ ELASTICCURL }} -s -k -L -H "Content-Type: application/json" "https://localhost:9200/${PATH}" "$@" +{{ ELASTICCURL }} -s -k -L -H "Content-Type: application/json" "https://localhost:9200/${QUERYPATH}" "$@" diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index d21ecc58c..0f36deae2 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -165,6 +165,7 @@ function syncElasticSystemRole() { } function syncElastic() { + echo "Syncing users between SOC and Elastic..." usersTmpFile="${elasticUsersFile}.tmp" rolesTmpFile="${elasticRolesFile}.tmp" createElasticFile "${usersTmpFile}" @@ -331,8 +332,8 @@ case "${operation}" in createUser "$email" syncAll echo "Successfully added new user to SOC" - check_container thehive && echo $password | so-thehive-user-add "$email" - check_container fleet && echo $password | so-fleet-user-add "$email" + check_container thehive && echo "$password" | so-thehive-user-add "$email" + check_container fleet && echo "$password" | so-fleet-user-add "$email" ;; "list") From a0c65e2333887e7f75f5e8346deff1896c2e68ce Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 9 Jun 2021 09:38:50 -0400 Subject: [PATCH 70/76] Ensure elastic minions also update their auth files --- salt/common/tools/sbin/so-user | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index 0f36deae2..ea278e941 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -221,6 +221,7 @@ function syncElastic() { if [[ -z "$SKIP_STATE_APPLY" ]]; then echo "Applying elastic state..." salt-call state.apply elasticsearch queue=True + salt -C 'G@role:so-node or G@role:so-heavynode' state.apply elasticsearch queue=True fi else echo "Generated users/roles files are incomplete; aborting." From 89a02383b8705bc42c944aef694d31d3a94c7f00 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Wed, 9 Jun 2021 16:31:32 -0400 Subject: [PATCH 71/76] Correct cronjob path issue for sysctl; suppress diff outputs from users/roles files; suppress salt state output during user sync --- salt/common/tools/sbin/so-user | 11 +++++++---- salt/elasticsearch/init.sls | 2 ++ salt/soc/init.sls | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user index ea278e941..54bcf7f71 100755 --- a/salt/common/tools/sbin/so-user +++ b/salt/common/tools/sbin/so-user @@ -219,12 +219,15 @@ function syncElastic() { mv "${rolesTmpFile}" "${elasticRolesFile}" if [[ -z "$SKIP_STATE_APPLY" ]]; then - echo "Applying elastic state..." - salt-call state.apply elasticsearch queue=True - salt -C 'G@role:so-node or G@role:so-heavynode' state.apply elasticsearch queue=True + echo "Applying elastic state locally; This can take a few minutes..." + echo "Applying elastic state locally at $(date)" >> /opt/so/log/soc/sync.log 2>&1 + salt-call state.apply elasticsearch queue=True >> /opt/so/log/soc/sync.log 2>&1 + echo "Applying elastic state to elastic minions; This can take a few minutes..." + echo "Applying elastic state to elastic minions at $(date)" >> /opt/so/log/soc/sync.log 2>&1 + salt -C 'G@role:so-node or G@role:so-heavynode' state.apply elasticsearch queue=True >> /opt/so/log/soc/sync.log 2>&1 fi else - echo "Generated users/roles files are incomplete; aborting." + echo "Newly generated users/roles files are incomplete; aborting." fi } diff --git a/salt/elasticsearch/init.sls b/salt/elasticsearch/init.sls index 05b58b79a..4045fa10f 100644 --- a/salt/elasticsearch/init.sls +++ b/salt/elasticsearch/init.sls @@ -178,6 +178,7 @@ auth_users: - user: 930 - group: 930 - mode: 600 + - show_changes: False auth_users_roles: file.managed: @@ -186,6 +187,7 @@ auth_users_roles: - user: 930 - group: 930 - mode: 600 + - show_changes: False auth_users_inode: require: diff --git a/salt/soc/init.sls b/salt/soc/init.sls index 5fe403934..01b57c8ce 100644 --- a/salt/soc/init.sls +++ b/salt/soc/init.sls @@ -65,7 +65,7 @@ soccustom: sosyncusers: cron.present: - user: root - - name: 'STALE_MIN=1 /usr/sbin/so-user sync &>> /opt/so/log/soc/sync.log' + - name: 'PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin STALE_MIN=1 /usr/sbin/so-user sync &>> /opt/so/log/soc/sync.log' so-soc: docker_container.running: From 7205c5cb7bc47d0e161dde49d43b3d364bb2ce2a Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Thu, 10 Jun 2021 15:21:03 -0400 Subject: [PATCH 72/76] Provide timestamp as arg to SOC PCAP pivots --- salt/soc/files/soc/menu.actions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/soc/files/soc/menu.actions.json b/salt/soc/files/soc/menu.actions.json index 558d10a36..665ca4c39 100644 --- a/salt/soc/files/soc/menu.actions.json +++ b/salt/soc/files/soc/menu.actions.json @@ -15,8 +15,8 @@ ]}, { "name": "actionPcap", "description": "actionPcapHelp", "icon": "fa-stream", "target": "", "links": [ - "/joblookup?esid={:soc_id}", - "/joblookup?ncid={:network.community_id}" + "/joblookup?esid={:soc_id}&time={:@timestamp}", + "/joblookup?ncid={:network.community_id}&time={:@timestamp}" ]}, { "name": "actionCyberChef", "description": "actionCyberChefHelp", "icon": "fas fa-bread-slice", "target": "_blank", "links": [ From 37f4caf536f7d6bb19c84647e2c8a7064637686d Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 14 Jun 2021 12:13:50 -0400 Subject: [PATCH 73/76] Make new ECS changes Elastic-auth compatible --- salt/common/tools/sbin/so-elastalert-create | 6 +++--- salt/common/tools/sbin/so-filebeat-module-setup | 6 +++--- salt/filebeat/etc/module-setup.yml | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/salt/common/tools/sbin/so-elastalert-create b/salt/common/tools/sbin/so-elastalert-create index 683b53ed1..56e1a5a25 100755 --- a/salt/common/tools/sbin/so-elastalert-create +++ b/salt/common/tools/sbin/so-elastalert-create @@ -145,9 +145,9 @@ EOF rulename=$(echo ${raw_rulename,,} | sed 's/ /_/g') cat << EOF >> "$rulename.yaml" -# Elasticsearch Host -es_host: elasticsearch -es_port: 9200 +# Elasticsearch Host Override (optional) +# es_host: elasticsearch +# es_port: 9200 # (Required) # Rule name, must be unique diff --git a/salt/common/tools/sbin/so-filebeat-module-setup b/salt/common/tools/sbin/so-filebeat-module-setup index 7a6ae7446..4f9811ca7 100755 --- a/salt/common/tools/sbin/so-filebeat-module-setup +++ b/salt/common/tools/sbin/so-filebeat-module-setup @@ -31,7 +31,7 @@ echo -n "Waiting for ElasticSearch..." COUNT=0 ELASTICSEARCH_CONNECTED="no" while [[ "$COUNT" -le 240 ]]; do - curl -k --output /dev/null --silent --head --fail -L https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" + {{ ELASTICCURL }} -k --output /dev/null --silent --head --fail -L https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" if [ $? -eq 0 ]; then ELASTICSEARCH_CONNECTED="yes" echo "connected!" @@ -48,8 +48,8 @@ if [ "$ELASTICSEARCH_CONNECTED" == "no" ]; then echo fi echo "Testing to see if the pipelines are already applied" -ESVER=$(curl -sk https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" |jq .version.number |tr -d \") -PIPELINES=$(curl -sk https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT"/_ingest/pipeline/filebeat-$ESVER-suricata-eve-pipeline | jq . | wc -c) +ESVER=$({{ ELASTICCURL }} -sk https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" |jq .version.number |tr -d \") +PIPELINES=$({{ ELASTICCURL }} -sk https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT"/_ingest/pipeline/filebeat-$ESVER-suricata-eve-pipeline | jq . | wc -c) if [[ "$PIPELINES" -lt 5 ]]; then echo "Setting up ingest pipeline(s)" diff --git a/salt/filebeat/etc/module-setup.yml b/salt/filebeat/etc/module-setup.yml index 431e432b3..35fbf5fbe 100644 --- a/salt/filebeat/etc/module-setup.yml +++ b/salt/filebeat/etc/module-setup.yml @@ -3,8 +3,12 @@ {%- else %} {%- set MANAGER = salt['grains.get']('master') %} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_beats_user:pass', '') %} output.elasticsearch: enabled: true hosts: ["https://{{ MANAGER }}:9200"] + username: "{{ ES_USER }}" + password: "{{ ES_PASS }}" ssl.certificate_authorities: ["/usr/share/filebeat/intraca.crt"] From 62187807f01ca156d8eab7163623259b1f81a45d Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 14 Jun 2021 14:08:14 -0400 Subject: [PATCH 74/76] Specify elastic creds for playbook alert templates --- salt/elastalert/files/modules/so/playbook-es.py | 7 ++++++- salt/soctopus/files/templates/es-generic.template | 4 ++++ salt/soctopus/files/templates/generic.template | 5 +++++ salt/soctopus/files/templates/osquery.template | 5 +++++ salt/soctopus/init.sls | 1 + 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/salt/elastalert/files/modules/so/playbook-es.py b/salt/elastalert/files/modules/so/playbook-es.py index ab2327ab7..5b1835bac 100644 --- a/salt/elastalert/files/modules/so/playbook-es.py +++ b/salt/elastalert/files/modules/so/playbook-es.py @@ -19,9 +19,14 @@ class PlaybookESAlerter(Alerter): today = strftime("%Y.%m.%d", gmtime()) timestamp = strftime("%Y-%m-%d"'T'"%H:%M:%S"'.000Z', gmtime()) headers = {"Content-Type": "application/json"} + + creds = None + if 'elasticsearch_user' in self.rule and 'elasticsearch_pass' in self.rule: + creds = (self.rule['elasticsearch_user'], self.rule['elasticsearch_pass']) + payload = {"rule": { "name": self.rule['play_title'],"case_template": self.rule['play_id'],"uuid": self.rule['play_id'],"category": self.rule['rule.category']},"event":{ "severity": self.rule['event.severity'],"module": self.rule['event.module'],"dataset": self.rule['event.dataset'],"severity_label": self.rule['sigma_level']},"kibana_pivot": self.rule['kibana_pivot'],"soc_pivot": self.rule['soc_pivot'],"play_url": self.rule['play_url'],"sigma_level": self.rule['sigma_level'],"event_data": match, "@timestamp": timestamp} url = f"https://{self.rule['elasticsearch_host']}/so-playbook-alerts-{today}/_doc/" - requests.post(url, data=json.dumps(payload), headers=headers, verify=False) + requests.post(url, data=json.dumps(payload), headers=headers, verify=False, auth=creds) def get_info(self): return {'type': 'PlaybookESAlerter'} \ No newline at end of file diff --git a/salt/soctopus/files/templates/es-generic.template b/salt/soctopus/files/templates/es-generic.template index 8183a5af4..6e50a3f3e 100644 --- a/salt/soctopus/files/templates/es-generic.template +++ b/salt/soctopus/files/templates/es-generic.template @@ -1,7 +1,11 @@ {% set ES = salt['pillar.get']('global:managerip', '') %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} alert: modules.so.playbook-es.PlaybookESAlerter elasticsearch_host: "{{ ES }}:9200" +elasticsearch_user: "{{ ES_USER }}" +elasticsearch_pass: "{{ ES_PASS }}" play_title: "" play_url: "https://{{ ES }}/playbook/issues/6000" sigma_level: "" diff --git a/salt/soctopus/files/templates/generic.template b/salt/soctopus/files/templates/generic.template index f956eb8a6..33d8b7ea5 100644 --- a/salt/soctopus/files/templates/generic.template +++ b/salt/soctopus/files/templates/generic.template @@ -1,8 +1,13 @@ {% set es = salt['pillar.get']('global:url_base', '') %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} + alert: - "modules.so.playbook-es.PlaybookESAlerter" elasticsearch_host: "{{ es }}:9200" +elasticsearch_user: "{{ ES_USER }}" +elasticsearch_pass: "{{ ES_PASS }}" play_title: "" play_id: "" event.module: "playbook" diff --git a/salt/soctopus/files/templates/osquery.template b/salt/soctopus/files/templates/osquery.template index 0410cb288..22c29193a 100644 --- a/salt/soctopus/files/templates/osquery.template +++ b/salt/soctopus/files/templates/osquery.template @@ -1,8 +1,13 @@ {% set es = salt['pillar.get']('global:url_base', '') %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %} + alert: - "modules.so.playbook-es.PlaybookESAlerter" elasticsearch_host: "{{ es }}:9200" +elasticsearch_user: "{{ ES_USER }}" +elasticsearch_pass: "{{ ES_PASS }}" play_title: "" event.module: "playbook" event.dataset: "alert" diff --git a/salt/soctopus/init.sls b/salt/soctopus/init.sls index c2c8dc1ac..984ff45a9 100644 --- a/salt/soctopus/init.sls +++ b/salt/soctopus/init.sls @@ -21,6 +21,7 @@ soctopus-sync: - source: salt://soctopus/files/templates - user: 939 - group: 939 + - mode: 600 - template: jinja soctopusconf: From 3891ca2929694dd2a9760f923eb6845bac7a88dc Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Mon, 14 Jun 2021 15:46:25 -0400 Subject: [PATCH 75/76] Use correct mode param to file.recurse --- salt/soctopus/init.sls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/soctopus/init.sls b/salt/soctopus/init.sls index 984ff45a9..1b1132f5a 100644 --- a/salt/soctopus/init.sls +++ b/salt/soctopus/init.sls @@ -21,7 +21,7 @@ soctopus-sync: - source: salt://soctopus/files/templates - user: 939 - group: 939 - - mode: 600 + - file_mode: 600 - template: jinja soctopusconf: From dd8eb29a1861205579c6c85aba8b5fc4057c2b44 Mon Sep 17 00:00:00 2001 From: Jason Ertel Date: Tue, 15 Jun 2021 09:11:58 -0400 Subject: [PATCH 76/76] Continue merge of ECS into Elastic Auth --- salt/curator/init.sls | 1 + salt/elastalert/init.sls | 1 + salt/filebeat/init.sls | 2 ++ salt/kibana/init.sls | 1 + salt/logstash/init.sls | 1 + .../so/9050_output_filebeatmodules.conf.jinja | 30 +++++++++++-------- salt/soctopus/init.sls | 1 + salt/telegraf/init.sls | 1 + 8 files changed, 25 insertions(+), 13 deletions(-) diff --git a/salt/curator/init.sls b/salt/curator/init.sls index 966b0b857..48a10b4b8 100644 --- a/salt/curator/init.sls +++ b/salt/curator/init.sls @@ -49,6 +49,7 @@ curconf: - source: salt://curator/files/curator.yml - user: 934 - group: 939 + - mode: 660 - template: jinja curcloseddel: diff --git a/salt/elastalert/init.sls b/salt/elastalert/init.sls index 8fcb46cda..205d6432e 100644 --- a/salt/elastalert/init.sls +++ b/salt/elastalert/init.sls @@ -99,6 +99,7 @@ elastaconf: elastalert_config: {{ elastalert_config.elastalert.config }} - user: 933 - group: 933 + - mode: 660 - template: jinja wait_for_elasticsearch: diff --git a/salt/filebeat/init.sls b/salt/filebeat/init.sls index c5d859307..1517226a3 100644 --- a/salt/filebeat/init.sls +++ b/salt/filebeat/init.sls @@ -1,3 +1,4 @@ + # Copyright 2014,2015,2016,2017,2018,2019,2020,2021 Security Onion Solutions, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -83,6 +84,7 @@ filebeatmoduleconfsync: - source: salt://filebeat/etc/module-setup.yml - user: root - group: root + - mode: 660 - template: jinja sodefaults_module_conf: diff --git a/salt/kibana/init.sls b/salt/kibana/init.sls index 61498cfeb..40ed8babc 100644 --- a/salt/kibana/init.sls +++ b/salt/kibana/init.sls @@ -35,6 +35,7 @@ synckibanaconfig: - source: salt://kibana/etc - user: 932 - group: 939 + - file_mode: 660 - template: jinja kibanalogdir: diff --git a/salt/logstash/init.sls b/salt/logstash/init.sls index 2c2c89626..bfd08e4fe 100644 --- a/salt/logstash/init.sls +++ b/salt/logstash/init.sls @@ -78,6 +78,7 @@ ls_pipeline_{{PL}}_{{CONFIGFILE.split('.')[0] | replace("/","_") }}: {% endif %} - user: 931 - group: 939 + - mode: 660 - makedirs: True {% endfor %} diff --git a/salt/logstash/pipelines/config/so/9050_output_filebeatmodules.conf.jinja b/salt/logstash/pipelines/config/so/9050_output_filebeatmodules.conf.jinja index 20e9f0c0a..01d57c9d6 100644 --- a/salt/logstash/pipelines/config/so/9050_output_filebeatmodules.conf.jinja +++ b/salt/logstash/pipelines/config/so/9050_output_filebeatmodules.conf.jinja @@ -3,18 +3,22 @@ {%- else %} {%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%} {%- endif %} +{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:user', '') %} +{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_logstash_user:pass', '') %} output { - if [metadata][pipeline] { - elasticsearch { - id => "filebeat_modules_metadata_pipeline" - pipeline => "%{[metadata][pipeline]}" - hosts => "{{ ES }}" - index => "so-%{[event][module]}-%{+YYYY.MM.dd}" - template_name => "so-common" - template => "/templates/so-common-template.json" - template_overwrite => true - ssl => true - ssl_certificate_verification => false - } - } + if [metadata][pipeline] { + elasticsearch { + id => "filebeat_modules_metadata_pipeline" + pipeline => "%{[metadata][pipeline]}" + hosts => "{{ ES }}" + user => "{{ ES_USER }}" + password => "{{ ES_PASS }}" + index => "so-%{[event][module]}-%{+YYYY.MM.dd}" + template_name => "so-common" + template => "/templates/so-common-template.json" + template_overwrite => true + ssl => true + ssl_certificate_verification => false + } + } } \ No newline at end of file diff --git a/salt/soctopus/init.sls b/salt/soctopus/init.sls index 1b1132f5a..b32c67487 100644 --- a/salt/soctopus/init.sls +++ b/salt/soctopus/init.sls @@ -44,6 +44,7 @@ playbookrulesdir: - name: /opt/so/rules/elastalert/playbook - user: 939 - group: 939 + - mode: 660 - makedirs: True playbookrulessync: diff --git a/salt/telegraf/init.sls b/salt/telegraf/init.sls index cea4d3f45..14373fe9d 100644 --- a/salt/telegraf/init.sls +++ b/salt/telegraf/init.sls @@ -38,6 +38,7 @@ tgrafconf: - name: /opt/so/conf/telegraf/etc/telegraf.conf - user: 939 - group: 939 + - mode: 660 - template: jinja - source: salt://telegraf/etc/telegraf.conf