mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2025-12-06 09:12:45 +01:00
Added new soc-related saltstack files.
This commit is contained in:
201
salt/common/tools/sbin/so-user
Executable file
201
salt/common/tools/sbin/so-user
Executable file
@@ -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 <list|add|update|delete|checkpw> [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 <<EOF
|
||||
{
|
||||
"addresses": [
|
||||
{
|
||||
"expires_at": "2099-01-31T12:00:00Z",
|
||||
"value": "${email}",
|
||||
"verified": true,
|
||||
"verified_at": "${now}",
|
||||
"via": "so-add-user"
|
||||
}
|
||||
],
|
||||
"traits": {"email":"${email}"},
|
||||
"traits_schema_id": "default"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
response=$(curl -Ss ${kratosUrl}/identities -d "$addUserJson")
|
||||
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
|
||||
|
||||
identityId=$(echo "${response}" | jq ".id")
|
||||
if [[ ${identityId} == "null" ]]; then
|
||||
code=$(echo "${response}" | jq ".error.code")
|
||||
[[ "${code}" == "409" ]] && fail "User already exists"
|
||||
|
||||
reason=$(echo "${response}" | jq ".error.message")
|
||||
[[ $? == 0 ]] && fail "Unable to add user: ${reason}"
|
||||
fi
|
||||
|
||||
updatePassword $identityId
|
||||
}
|
||||
|
||||
function updateUser() {
|
||||
email=$1
|
||||
|
||||
identityId=$(findIdByEmail "$email")
|
||||
[[ ${identityId} == "" ]] && fail "User not found"
|
||||
|
||||
updatePassword $identityId
|
||||
}
|
||||
|
||||
function deleteUser() {
|
||||
email=$1
|
||||
|
||||
identityId=$(findIdByEmail "$email")
|
||||
[[ ${identityId} == "" ]] && fail "User not found"
|
||||
|
||||
response=$(curl -Ss -XDELETE "${kratosUrl}/identities/$identityId")
|
||||
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
|
||||
}
|
||||
|
||||
case "${operation}" in
|
||||
"add")
|
||||
[[ "$email" == "" ]] && fail "Email address must be provided"
|
||||
|
||||
createUser "$email"
|
||||
echo "Successfully added new user"
|
||||
;;
|
||||
|
||||
"list")
|
||||
listUsers
|
||||
;;
|
||||
|
||||
"update")
|
||||
[[ "$email" == "" ]] && fail "Email address must be provided"
|
||||
|
||||
updateUser "$email"
|
||||
echo "Successfully updated user"
|
||||
;;
|
||||
|
||||
"delete")
|
||||
[[ "$email" == "" ]] && fail "Email address must be provided"
|
||||
|
||||
deleteUser "$email"
|
||||
echo "Successfully deleted user"
|
||||
;;
|
||||
|
||||
"checkpw")
|
||||
updatePassword
|
||||
echo "Password is acceptable"
|
||||
;;
|
||||
|
||||
*)
|
||||
fail "Unsupported operation: $operation"
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
78
salt/soc/files/kratos/kratos.yaml
Normal file
78
salt/soc/files/kratos/kratos.yaml
Normal file
@@ -0,0 +1,78 @@
|
||||
{%- set WEBACCESS = salt['pillar.get']('kratos:redirect', '') -%}
|
||||
{%- set KRATOSKEY = salt['pillar.get']('kratos:kratoskey', '') -%}
|
||||
|
||||
selfservice:
|
||||
strategies:
|
||||
password:
|
||||
enabled: true
|
||||
|
||||
verify:
|
||||
return_to: https://{{ WEBACCESS }}/
|
||||
|
||||
logout:
|
||||
redirect_to: https://{{ WEBACCESS }}/login/
|
||||
|
||||
login:
|
||||
request_lifespan: 10m
|
||||
after:
|
||||
password:
|
||||
-
|
||||
job: session
|
||||
-
|
||||
job: redirect
|
||||
config:
|
||||
default_redirect_url: https://{{ WEBACCESS }}/
|
||||
allow_user_defined_redirect: true
|
||||
|
||||
registration:
|
||||
request_lifespan: 10m
|
||||
after:
|
||||
password:
|
||||
-
|
||||
job: verify
|
||||
-
|
||||
job: session
|
||||
-
|
||||
job: redirect
|
||||
config:
|
||||
default_redirect_url: https://{{ WEBACCESS }}/
|
||||
allow_user_defined_redirect: true
|
||||
|
||||
log:
|
||||
level: debug
|
||||
format: json
|
||||
|
||||
secrets:
|
||||
session:
|
||||
- {{ KRATOSKEY }}
|
||||
|
||||
urls:
|
||||
login_ui: https://{{ WEBACCESS }}/login/
|
||||
registration_ui: https://{{ WEBACCESS }}/login/
|
||||
error_ui: https://{{ WEBACCESS }}/login/
|
||||
profile_ui: https://{{ WEBACCESS }}/
|
||||
verify_ui: https://{{ WEBACCESS }}/
|
||||
mfa_ui: https://{{ WEBACCESS }}/
|
||||
|
||||
self:
|
||||
public: https://{{ WEBACCESS }}/auth/
|
||||
admin: https://{{ WEBACCESS }}/kratos/
|
||||
default_return_to: https://{{ WEBACCESS }}/
|
||||
whitelisted_return_to_domains:
|
||||
- http://127.0.0.1
|
||||
|
||||
hashers:
|
||||
argon2:
|
||||
parallelism: 2
|
||||
memory: 16384
|
||||
iterations: 3
|
||||
salt_length: 16
|
||||
key_length: 32
|
||||
|
||||
identity:
|
||||
traits:
|
||||
default_schema_url: file:///kratos-conf/schema.json
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtps://{{ WEBACCESS }}:25
|
||||
28
salt/soc/files/kratos/schema.json
Normal file
28
salt/soc/files/kratos/schema.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"$id": "securityonion.schema.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Person",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
"title": "E-Mail",
|
||||
"minLength": 6,
|
||||
"ory.sh/kratos": {
|
||||
"credentials": {
|
||||
"password": {
|
||||
"identifier": true
|
||||
}
|
||||
},
|
||||
"verification": {
|
||||
"via": "email"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
23
salt/soc/files/soc/changes.json
Normal file
23
salt/soc/files/soc/changes.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"title": "Introducing Hybrid Hunter 1.2.1 Beta",
|
||||
"changes": [
|
||||
{ "summary": "New authentication framework" },
|
||||
{ "summary": "New Logstash pipeline setup. Now uses multiple pipelines." },
|
||||
{ "summary": "New Master + Search node type and well as a Heavy Node type in the install." },
|
||||
{ "summary": "Change all nodes to point to the docker registry on the Master. This cuts down on the calls to dockerhub." },
|
||||
{ "summary": "Upgraded to Zeek 3.0" },
|
||||
{ "summary": "Upgraded to Elastic 7.6" },
|
||||
{ "summary": "New SO Start | Stop | Restart scripts for all components (eg. `so-playbook-restart`)." },
|
||||
{ "summary": "BPF support for Suricata (NIDS), Steno (PCAP) & Zeek (<a target='new' href='https://github.com/Security-Onion-Solutions/securityonion-saltstack/wiki/BPF'>More Info</a>)." },
|
||||
{ "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." }
|
||||
]
|
||||
}
|
||||
26
salt/soc/files/soc/soc.json
Normal file
26
salt/soc/files/soc/soc.json
Normal file
@@ -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 }}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
97
salt/soc/init.sls
Normal file
97
salt/soc/init.sls
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user