diff --git a/salt/common/tools/sbin/so-user b/salt/common/tools/sbin/so-user new file mode 100755 index 000000000..c7fd19a4c --- /dev/null +++ b/salt/common/tools/sbin/so-user @@ -0,0 +1,201 @@ +#!/bin/bash +# Copyright 2020 Security Onion Solutions. All rights reserved. +# +# This program is distributed under the terms of version 2 of the +# GNU General Public License. See LICENSE for further details. +# +# 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. + +got_root() { + + # Make sure you are root + if [ "$(id -u)" -ne 0 ]; then + echo "This script must be run using sudo!" + exit 1 + fi + +} + +# Make sure the user is root +got_root + +if [[ $# < 1 || $# > 2 ]]; then + echo "Usage: $0 [email]" + echo "Note that checkpw only checks that the given password meets the minimum requirements, it does not test that it matches for an existing user." + exit 1 +fi + +operation=$1 +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} + +function fail() { + msg=$1 + echo "$1" + exit 1 +} + +function require() { + cmd=$1 + which "$1" 2>&1 > /dev/null + [[ $? != 0 ]] && fail "This script requires the following command be installed: ${cmd}" +} + +# Verify this environment is capable of running this script +require "argon2" +require "jq" +require "curl" +require "openssl" +require "sqlite3" +[[ ! -f $databasePath ]] && fail "Unable to find database file; specify path via KRATOS_DB_PATH environment variable" +response=$(curl -Ss ${kratosUrl}/) +[[ "$response" != "404 page not found" ]] && fail "Unable to communicate with Kratos; specify URL via KRATOS_URL environment variable" + +function findIdByEmail() { + email=$1 + + response=$(curl -Ss ${kratosUrl}/identities) + identityId=$(echo "${response}" | jq ".[] | select(.addresses[0].value == \"$email\") | .id") + echo $identityId +} + +function validatePassword() { + password=$1 + + len=$(expr length "$password") + if [[ $len -lt 6 ]]; then + echo "Password does not meet the minimum requirements" + exit 2 + fi +} + +function updatePassword() { + identityId=$1 + + # Read password from stdin (show prompt only if no stdin was piped in) + test -t 0 + if [[ $? == 0 ]]; then + echo "Enter new password:" + fi + read -s password + + validatePassword "$password" + + 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) + + # 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 listUsers() { + response=$(curl -Ss ${kratosUrl}/identities) + [[ $? != 0 ]] && fail "Unable to communicate with Kratos" + + echo "${response}" | jq -r ".[] | .addresses[0].value" | sort +} + +function createUser() { + email=$1 + + now=$(date -u +%FT%TZ) + addUserJson=$(cat <More Info)." }, + { "summary": "Updated Domain Stats & Frequency Server containers to Python3 & created new Salt states for them." }, + { "summary": "Added so-status script which gives an easy to read look at container status." }, + { "summary": "Manage threshold.conf for Suricata using the thresholding pillar." }, + { "summary": "The ISO now includes all the docker containers for faster install speeds." }, + { "summary": "You now set the password for the onion account during the iso install. This account is temporary and will be removed after so-setup." }, + { "summary": "Updated Helix parsers for better compatibility." }, + { "summary": "Updated telegraf docker to include curl and jq." }, + { "summary": "CVE-2020-0601 Zeek Detection Script." }, + { "summary": "ISO Install now prompts you to create a password for the onion user during imaging. This account gets disabled during setup." }, + { "summary": "Check out the Hybrid Hunter Quick Start Guide." } + ] +} diff --git a/salt/soc/files/soc/soc.json b/salt/soc/files/soc/soc.json new file mode 100644 index 000000000..f69a66117 --- /dev/null +++ b/salt/soc/files/soc/soc.json @@ -0,0 +1,26 @@ +{%- set MASTERIP = salt['pillar.get']('static:masterip', '') -%} +{%- set SENSORONIKEY = salt['pillar.get']('static:sensoronikey', '') -%} +{ + "logFilename": "/opt/sensoroni/logs/sensoroni-server.log", + "server": { + "bindAddress": "0.0.0.0:9822", + "baseUrl": "/", + "maxPacketCount": 5000, + "htmlDir": "html", + "modules": { + "filedatastore": { + "jobDir": "jobs" + }, + "securityonion": { + "elasticsearchHost": "http://{{ MASTERIP }}:9200", + "elasticsearchUsername": "", + "elasticsearchPassword": "", + "elasticsearchVerifyCert": false + }, + "statickeyauth": { + "anonymousCidr": "172.17.0.0/24", + "apiKey": "{{ SENSORONIKEY }}" + } + } + } +} diff --git a/salt/soc/init.sls b/salt/soc/init.sls new file mode 100644 index 000000000..7e67d1202 --- /dev/null +++ b/salt/soc/init.sls @@ -0,0 +1,97 @@ +{% set VERSION = salt['pillar.get']('static:soversion', 'HH1.2.1') %} +{% set MASTER = salt['grains.get']('master') %} + +socdir: + file.directory: + - name: /opt/so/conf/soc + - user: 939 + - group: 939 + - makedirs: True + +socdatadir: + file.directory: + - name: /nsm/soc/jobs + - user: 939 + - group: 939 + - makedirs: True + +soclogdir: + file.directory: + - name: /opt/so/log/soc + - user: 939 + - group: 939 + - makedirs: True + +socsync: + file.recurse: + - name: /opt/so/conf/soc + - source: salt://soc/files/soc + - user: 939 + - group: 939 + - template: jinja + +so-soc: + docker_container.running: + - image: {{ MASTER }}:5000/soshybridhunter/so-soc:{{ VERSION }} + - hostname: soc + - name: so-soc + - binds: + - /nsm/soc/jobs:/opt/sensoroni/jobs:rw + - /opt/so/conf/soc/soc.json:/opt/sensoroni/sensoroni.json:ro + - /opt/so/conf/soc/changes.json:/opt/sensoroni/html/changes.json:ro + - /opt/so/log/soc/:/opt/sensoroni/logs/:rw + - port_bindings: + - 0.0.0.0:9822:9822 + - watch: + - file: /opt/so/conf/soc + +# Add Kratos Group +kratosgroup: + group.present: + - name: kratos + - gid: 928 + +# Add Kratos user +kratos: + user.present: + - uid: 928 + - gid: 928 + - home: /opt/so/conf/kratos + +kratosdir: + file.directory: + - name: /opt/so/conf/kratos/db + - user: 928 + - group: 928 + - makedirs: True + +kratoslogdir: + file.directory: + - name: /opt/so/log/kratos + - user: 928 + - group: 928 + - makedirs: True + +kratossync: + file.recurse: + - name: /opt/so/conf/kratos + - source: salt://soc/files/kratos + - user: 928 + - group: 928 + - template: jinja + +so-kratos: + docker_container.running: + - image: {{ MASTER }}:5000/soshybridhunter/so-kratos:{{ VERSION }} + - hostname: kratos + - name: so-kratos + - binds: + - /opt/so/conf/kratos/schema.json:/kratos-conf/schema.json:ro + - /opt/so/conf/kratos/kratos.yaml:/kratos-conf/kratos.yaml:ro + - /opt/so/log/kratos/:/kratos-log:rw + - /opt/so/conf/kratos/db:/kratos-data:rw + - port_bindings: + - 0.0.0.0:4433:4433 + - 0.0.0.0:4434:4434 + - watch: + - file: /opt/so/conf/kratos