mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2025-12-06 09:12:45 +01:00
700 lines
22 KiB
Bash
Executable File
700 lines
22 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
|
|
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
|
|
# https://securityonion.net/license; you may not use this file except in compliance with the
|
|
# Elastic License 2.0.
|
|
|
|
|
|
|
|
source $(dirname $0)/so-common
|
|
|
|
DEFAULT_ROLE=analyst
|
|
|
|
function usage() {
|
|
cat <<USAGE_EOF
|
|
Usage: $0 <operation> [supporting parameters]
|
|
|
|
where <operation> is one of the following:
|
|
|
|
list: Lists all user email addresses currently defined in the identity system
|
|
|
|
add: Adds a new user to the identity system
|
|
Required parameters:
|
|
--email <email>
|
|
Optional parameters:
|
|
--role <role> (defaults to $DEFAULT_ROLE)
|
|
--firstName <firstName> (defaults to blank)
|
|
--lastName <lastName> (defaults to blank)
|
|
--note <note> (defaults to blank)
|
|
--skip-sync (defers the Elastic sync until the next scheduled time)
|
|
|
|
addrole: Grants a role to an existing user
|
|
Required parameters:
|
|
--email <email>
|
|
--role <role>
|
|
Optional parameters:
|
|
--skip-sync (defers the Elastic sync until the next scheduled time)
|
|
|
|
delrole: Removes a role from an existing user
|
|
Required parameters:
|
|
--email <email>
|
|
--role <role>
|
|
Optional parameters:
|
|
--skip-sync (defers the Elastic sync until the next scheduled time)
|
|
|
|
password: Updates a user's password and disables MFA
|
|
Required parameters:
|
|
--email <email>
|
|
Optional parameters:
|
|
--skip-sync (defers the Elastic sync until the next scheduled time)
|
|
|
|
profile: Updates a user's profile information
|
|
Required parameters:
|
|
--email <email>
|
|
Optional parameters:
|
|
--role <role> (defaults to $DEFAULT_ROLE)
|
|
--firstName <firstName> (defaults to blank)
|
|
--lastName <lastName> (defaults to blank)
|
|
--note <note> (defaults to blank)
|
|
|
|
enable: Enables a user
|
|
Required parameters:
|
|
--email <email>
|
|
Optional parameters:
|
|
--skip-sync (defers the Elastic sync until the next scheduled time)
|
|
|
|
disable: Disables a user
|
|
Required parameters:
|
|
--email <email>
|
|
Optional parameters:
|
|
--skip-sync (defers the Elastic sync until the next scheduled time)
|
|
|
|
validate: Validates that the given email address and password are acceptable
|
|
Required parameters:
|
|
--email <email>
|
|
|
|
valemail: Validates that the given email address is acceptable; requires 'email' parameter
|
|
Required parameters:
|
|
--email <email>
|
|
|
|
valpass: Validates that a password is acceptable
|
|
|
|
Note that the password can be piped into STDIN to avoid prompting for it
|
|
USAGE_EOF
|
|
exit 1
|
|
}
|
|
|
|
if [[ $# -lt 1 || $1 == --help || $1 == -h || $1 == -? || $1 == --h ]]; then
|
|
usage
|
|
fi
|
|
|
|
operation=$1
|
|
shift
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
param=$1
|
|
shift
|
|
case "$param" in
|
|
--email)
|
|
email=$1
|
|
shift
|
|
;;
|
|
--role)
|
|
role=$1
|
|
shift
|
|
;;
|
|
--firstName)
|
|
firstName=$1
|
|
shift
|
|
;;
|
|
--lastName)
|
|
lastName=$1
|
|
shift
|
|
;;
|
|
--note)
|
|
note=$1
|
|
shift
|
|
;;
|
|
--skip-sync)
|
|
SKIP_SYNC=1
|
|
;;
|
|
*)
|
|
echo "Encountered unexpected parameter: $param"
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
kratosUrl=${KRATOS_URL:-http://127.0.0.1:4434/admin}
|
|
databasePath=${KRATOS_DB_PATH:-/nsm/kratos/db/db.sqlite}
|
|
databaseTimeout=${KRATOS_DB_TIMEOUT:-5000}
|
|
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}
|
|
socRolesFile=${SOC_ROLES_FILE:-/opt/so/conf/soc/soc_users_roles}
|
|
esUID=${ELASTIC_UID:-930}
|
|
esGID=${ELASTIC_GID:-930}
|
|
soUID=${SOCORE_UID:-939}
|
|
soGID=${SOCORE_GID:-939}
|
|
|
|
function lock() {
|
|
# Obtain file descriptor lock
|
|
exec 99>/var/tmp/so-user.lock || fail "Unable to create lock descriptor; if the system was not shutdown gracefully you may need to remove /var/tmp/so-user.lock manually."
|
|
flock -w 10 99 || fail "Another process is using so-user; if the system was not shutdown gracefully you may need to remove /var/tmp/so-user.lock manually."
|
|
trap 'rm -f /var/tmp/so-user.lock' EXIT
|
|
}
|
|
|
|
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
|
|
function verifyEnvironment() {
|
|
require "htpasswd"
|
|
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 -L ${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 -L ${kratosUrl}/identities)
|
|
identityId=$(echo "${response}" | jq -r ".[] | select(.verifiable_addresses[0].value == \"$email\") | .id")
|
|
echo $identityId
|
|
}
|
|
|
|
function validatePassword() {
|
|
password=$1
|
|
|
|
len=$(expr length "$password")
|
|
if [[ $len -lt 8 ]]; then
|
|
fail "Password does not meet the minimum requirements"
|
|
fi
|
|
if [[ $len -gt 72 ]]; then
|
|
fail "Password is too long (max: 72)"
|
|
fi
|
|
check_password_and_exit "$password"
|
|
}
|
|
|
|
function validateEmail() {
|
|
email=$1
|
|
# (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
|
|
if [[ ! "$email" =~ ^[[:alnum:]._%+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}$ ]]; then
|
|
fail "Email address is invalid"
|
|
fi
|
|
|
|
if [[ "$email" =~ [A-Z] ]]; then
|
|
fail "Email addresses cannot contain uppercase letters"
|
|
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
|
|
|
|
if [ -z "$password" ]; then
|
|
# 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 -rs password
|
|
|
|
validatePassword "$password"
|
|
fi
|
|
|
|
if [[ -n "$identityId" ]]; then
|
|
# Generate password hash
|
|
passwordHash=$(hashPassword "$password")
|
|
# Update DB with new hash
|
|
echo "update identity_credentials set config=CAST('{\"hashed_password\":\"$passwordHash\"}' as BLOB), created_at=datetime('now'), updated_at=datetime('now') where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name='password');" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath"
|
|
# Deactivate MFA
|
|
echo "delete from identity_credential_identifiers where identity_credential_id=(select id from identity_credentials where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name='totp'));" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath"
|
|
echo "delete from identity_credentials where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name='totp');" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath"
|
|
[[ $? != 0 ]] && fail "Unable to update password"
|
|
fi
|
|
}
|
|
|
|
function createFile() {
|
|
filename=$1
|
|
uid=$2
|
|
gid=$3
|
|
|
|
mkdir -p $(dirname "$filename")
|
|
truncate -s 0 "$filename"
|
|
chmod 600 "$filename"
|
|
chown "${uid}:${gid}" "$filename"
|
|
}
|
|
|
|
function ensureRoleFileExists() {
|
|
if [[ ! -f "$socRolesFile" || ! -s "$socRolesFile" ]]; then
|
|
# Generate the new users file
|
|
rolesTmpFile="${socRolesFile}.tmp"
|
|
createFile "$rolesTmpFile" "$soUID" "$soGID"
|
|
|
|
if [[ -f "$databasePath" ]]; then
|
|
echo "Migrating roles to new file: $socRolesFile"
|
|
|
|
echo "select 'superuser:' || id from identities;" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" \
|
|
>> "$rolesTmpFile"
|
|
[[ $? != 0 ]] && fail "Unable to read identities from database"
|
|
|
|
echo "The following users have all been migrated with the super user role:"
|
|
cat "${rolesTmpFile}"
|
|
else
|
|
echo "Database file does not exist yet, installation is likely not yet complete."
|
|
fi
|
|
|
|
if [[ -d "$socRolesFile" ]]; then
|
|
echo "Removing invalid roles directory created by Docker"
|
|
rm -fr "$socRolesFile"
|
|
fi
|
|
mv "${rolesTmpFile}" "${socRolesFile}"
|
|
fi
|
|
}
|
|
|
|
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() {
|
|
[[ -n $SKIP_SYNC ]] && return
|
|
|
|
echo "Syncing users and roles between SOC and Elastic..."
|
|
|
|
usersTmpFile="${elasticUsersFile}.tmp"
|
|
createFile "${usersTmpFile}" "$esUID" "$esGID"
|
|
rolesTmpFile="${elasticRolesFile}.tmp"
|
|
createFile "${rolesTmpFile}" "$esUID" "$esGID"
|
|
|
|
authPillarJson=$(lookup_salt_value "auth" "elasticsearch" "pillar" "json")
|
|
|
|
syncElasticSystemUser "$authPillarJson" "so_elastic_user" "$usersTmpFile"
|
|
syncElasticSystemUser "$authPillarJson" "so_kibana_user" "$usersTmpFile"
|
|
syncElasticSystemUser "$authPillarJson" "so_logstash_user" "$usersTmpFile"
|
|
syncElasticSystemUser "$authPillarJson" "so_beats_user" "$usersTmpFile"
|
|
syncElasticSystemUser "$authPillarJson" "so_monitor_user" "$usersTmpFile"
|
|
|
|
syncElasticSystemRole "$authPillarJson" "so_elastic_user" "superuser" "$rolesTmpFile"
|
|
syncElasticSystemRole "$authPillarJson" "so_kibana_user" "kibana_system" "$rolesTmpFile"
|
|
syncElasticSystemRole "$authPillarJson" "so_logstash_user" "superuser" "$rolesTmpFile"
|
|
syncElasticSystemRole "$authPillarJson" "so_beats_user" "superuser" "$rolesTmpFile"
|
|
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" && -f "$socRolesFile" ]]; then
|
|
# Append the SOC users
|
|
userData=$(echo "select '{\"user\":\"' || ici.identifier || '\", \"data\":' || ic.config || '}'" \
|
|
"from identity_credential_identifiers ici, identity_credentials ic, identities i, identity_credential_types ict " \
|
|
"where " \
|
|
" ici.identity_credential_id=ic.id " \
|
|
" and ic.identity_id=i.id " \
|
|
" and ict.id=ic.identity_credential_type_id " \
|
|
" and ict.name='password' " \
|
|
" and instr(ic.config, 'hashed_password') " \
|
|
" and i.state == 'active' " \
|
|
"order by ici.identifier;" | \
|
|
sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath")
|
|
[[ $? != 0 ]] && fail "Unable to read credential hashes from database"
|
|
echo "${userData}" | \
|
|
jq -r '.user + ":" + .data.hashed_password' \
|
|
>> "$usersTmpFile"
|
|
|
|
# Append the user roles
|
|
while IFS="" read -r rolePair || [ -n "$rolePair" ]; do
|
|
userId=$(echo "$rolePair" | cut -d: -f2)
|
|
role=$(echo "$rolePair" | cut -d: -f1)
|
|
echo "select '$role:' || ici.identifier " \
|
|
"from identity_credential_identifiers ici, identity_credentials ic, identity_credential_types ict " \
|
|
"where ici.identity_credential_id=ic.id " \
|
|
" and ict.id=ic.identity_credential_type_id " \
|
|
" and ict.name='password' " \
|
|
" and ic.identity_id = '$userId';" | \
|
|
sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" >> "$rolesTmpFile"
|
|
[[ $? != 0 ]] && fail "Unable to read role identities from database"
|
|
done < "$socRolesFile"
|
|
|
|
else
|
|
echo "Database file or soc roles file does not exist yet, skipping users export"
|
|
fi
|
|
|
|
if [[ -s "${usersTmpFile}" ]]; then
|
|
mv "${usersTmpFile}" "${elasticUsersFile}"
|
|
mv "${rolesTmpFile}" "${elasticRolesFile}"
|
|
|
|
if [[ -z "$SKIP_STATE_APPLY" ]]; then
|
|
echo "Elastic state will be re-applied to affected minions. This will run in the background and may take several minutes to complete."
|
|
echo "Applying elastic state to elastic minions at $(date)" >> /opt/so/log/soc/sync.log 2>&1
|
|
salt --async -C 'G@role:so-standalone or G@role:so-eval or G@role:so-import or G@role:so-manager or G@role:so-managersearch or G@role:so-searchnode or G@role:so-heavynode' state.apply elasticsearch queue=True >> /opt/so/log/soc/sync.log 2>&1
|
|
fi
|
|
else
|
|
echo "Newly generated users/roles files are incomplete; aborting."
|
|
fi
|
|
}
|
|
|
|
function syncAll() {
|
|
ensureRoleFileExists
|
|
|
|
# Check if a sync is needed. Sync is not needed if the following are true:
|
|
# - user database entries are all older than the elastic users file
|
|
# - soc roles file last modify date is older than the elastic roles file
|
|
if [[ -z "$FORCE_SYNC" && -f "$databasePath" && -f "$elasticUsersFile" ]]; then
|
|
usersFileAgeSecs=$(echo $(($(date +%s) - $(date +%s -r "$elasticUsersFile"))))
|
|
staleCount=$(echo "select count(*) from identity_credentials where updated_at >= Datetime('now', '-${usersFileAgeSecs} seconds');" \
|
|
| sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath")
|
|
[[ $? != 0 ]] && fail "Unable to read user count from database"
|
|
if [[ "$staleCount" == "0" && "$elasticRolesFile" -nt "$socRolesFile" ]]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
syncElastic
|
|
|
|
return 0
|
|
}
|
|
|
|
function listUsers() {
|
|
response=$(curl -Ss -L ${kratosUrl}/identities)
|
|
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
|
|
|
|
users=$(echo "${response}" | jq -r ".[] | .verifiable_addresses[0].value" | sort)
|
|
for user in $users; do
|
|
roles=$(grep ":$user\$" "$elasticRolesFile" | cut -d: -f1 | tr '\n' ' ')
|
|
echo "$user: $roles"
|
|
done
|
|
}
|
|
|
|
function addUserRole() {
|
|
email=$1
|
|
role=$2
|
|
|
|
adjustUserRole "$email" "$role" "add"
|
|
}
|
|
|
|
function deleteUserRole() {
|
|
email=$1
|
|
role=$2
|
|
|
|
adjustUserRole "$email" "$role" "del"
|
|
}
|
|
|
|
function adjustUserRole() {
|
|
email=$1
|
|
role=$2
|
|
op=$3
|
|
|
|
identityId=$(findIdByEmail "$email")
|
|
[[ ${identityId} == "" ]] && fail "User not found"
|
|
|
|
ensureRoleFileExists
|
|
|
|
filename="$socRolesFile"
|
|
hasRole=0
|
|
grep "^$role:" "$socRolesFile" | grep -q "$identityId" && hasRole=1
|
|
if [[ "$op" == "add" ]]; then
|
|
if [[ "$hasRole" == "1" ]]; then
|
|
echo "User '$email' already has the role: $role"
|
|
return 1
|
|
else
|
|
echo "$role:$identityId" >> "$filename"
|
|
fi
|
|
elif [[ "$op" == "del" ]]; then
|
|
if [[ "$hasRole" -ne 1 ]]; then
|
|
fail "User '$email' does not have the role: $role"
|
|
else
|
|
sed "/^$role:$identityId\$/d" "$filename" > "$filename.tmp"
|
|
cat "$filename".tmp > "$filename"
|
|
rm -f "$filename".tmp
|
|
fi
|
|
else
|
|
fail "Unsupported role adjustment operation: $op"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function createUser() {
|
|
email=$1
|
|
role=$2
|
|
firstName=$3
|
|
lastName=$4
|
|
note=$5
|
|
|
|
now=$(date -u +%FT%TZ)
|
|
addUserJson=$(cat <<EOF
|
|
{
|
|
"traits": {
|
|
"email": "${email}",
|
|
"firstName": "${firstName}",
|
|
"lastName": "${lastName}",
|
|
"note": "${note}"
|
|
},
|
|
"schema_id": "default"
|
|
}
|
|
EOF
|
|
)
|
|
|
|
response=$(curl -Ss -L ${kratosUrl}/identities -d "$addUserJson")
|
|
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
|
|
|
|
identityId=$(echo "${response}" | jq -r ".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}"
|
|
else
|
|
updatePassword "$identityId"
|
|
addUserRole "$email" "$role"
|
|
fi
|
|
}
|
|
|
|
function updateStatus() {
|
|
email=$1
|
|
status=$2
|
|
|
|
identityId=$(findIdByEmail "$email")
|
|
[[ ${identityId} == "" ]] && fail "User not found"
|
|
|
|
response=$(curl -Ss -L "${kratosUrl}/identities/$identityId")
|
|
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
|
|
|
|
schemaId=$(echo "$response" | jq -r .schema_id)
|
|
|
|
# Capture traits and remove obsolete 'status' trait if exists
|
|
traitBlock=$(echo "$response" | jq -c .traits | sed -re 's/,?"status":".*?"//')
|
|
|
|
state="active"
|
|
if [[ "$status" == "locked" ]]; then
|
|
state="inactive"
|
|
fi
|
|
body="{ \"schema_id\": \"$schemaId\", \"state\": \"$state\", \"traits\": $traitBlock }"
|
|
response=$(curl -fSsL -XPUT -H "Content-Type: application/json" "${kratosUrl}/identities/$identityId" -d "$body")
|
|
[[ $? != 0 ]] && fail "Unable to update user"
|
|
}
|
|
|
|
function updateUserPassword() {
|
|
email=$1
|
|
|
|
identityId=$(findIdByEmail "$email")
|
|
[[ ${identityId} == "" ]] && fail "User not found"
|
|
|
|
updatePassword "$identityId"
|
|
}
|
|
|
|
function updateUserProfile() {
|
|
email=$1
|
|
|
|
identityId=$(findIdByEmail "$email")
|
|
[[ ${identityId} == "" ]] && fail "User not found"
|
|
|
|
response=$(curl -Ss -L "${kratosUrl}/identities/$identityId")
|
|
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
|
|
|
|
schemaId=$(echo "$response" | jq -r .schema_id)
|
|
state=$(echo "$response" | jq -r .state)
|
|
|
|
traitBlock="{\"email\":\"$email\",\"firstName\":\"$firstName\",\"lastName\":\"$lastName\",\"note\":\"$note\"}"
|
|
|
|
body="{ \"schema_id\": \"$schemaId\", \"state\": \"$state\", \"traits\": $traitBlock }"
|
|
response=$(curl -fSsL -XPUT -H "Content-Type: application/json" "${kratosUrl}/identities/$identityId" -d "$body")
|
|
[[ $? != 0 ]] && fail "Unable to update user"
|
|
}
|
|
|
|
function deleteUser() {
|
|
email=$1
|
|
|
|
identityId=$(findIdByEmail "$email")
|
|
[[ ${identityId} == "" ]] && fail "User not found"
|
|
|
|
response=$(curl -Ss -XDELETE -L "${kratosUrl}/identities/$identityId")
|
|
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
|
|
|
|
rolesTmpFile="${socRolesFile}.tmp"
|
|
createFile "$rolesTmpFile" "$soUID" "$soGID"
|
|
grep -v "$identityId" "$socRolesFile" > "$rolesTmpFile"
|
|
cat "$rolesTmpFile" > "$socRolesFile"
|
|
}
|
|
|
|
case "${operation}" in
|
|
"add")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
|
|
lock
|
|
validateEmail "$email"
|
|
updatePassword
|
|
createUser "$email" "${role:-$DEFAULT_ROLE}" "${firstName}" "${lastName}" "${note}"
|
|
syncAll
|
|
echo "Successfully added new user to SOC"
|
|
echo "$password" | so-influxdb-manage useradd "$email"
|
|
if [[ "$role" == "superuser" ]]; then
|
|
echo "$password" | so-influxdb-manage userpromote "$email"
|
|
fi
|
|
;;
|
|
|
|
"list")
|
|
verifyEnvironment
|
|
listUsers
|
|
;;
|
|
|
|
"addrole")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
[[ "$role" == "" ]] && fail "Role must be provided"
|
|
|
|
lock
|
|
validateEmail "$email"
|
|
if addUserRole "$email" "$role"; then
|
|
syncElastic
|
|
echo "Successfully added role to user"
|
|
if [[ "$role" == "superuser" ]]; then
|
|
echo "$password" | so-influxdb-manage userpromote "$email"
|
|
fi
|
|
fi
|
|
;;
|
|
|
|
"delrole")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
[[ "$role" == "" ]] && fail "Role must be provided"
|
|
|
|
lock
|
|
validateEmail "$email"
|
|
deleteUserRole "$email" "$role"
|
|
syncElastic
|
|
echo "Successfully removed role from user"
|
|
if [[ "$role" == "superuser" ]]; then
|
|
echo "$password" | so-influxdb-manage userdemote "$email"
|
|
fi
|
|
;;
|
|
|
|
"password")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
|
|
lock
|
|
updateUserPassword "$email"
|
|
syncAll
|
|
echo "Successfully updated user password"
|
|
echo "$password" | so-influxdb-manage userpass "$email"
|
|
;;
|
|
|
|
"profile")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
|
|
lock
|
|
updateUserProfile "$email"
|
|
echo "Successfully updated user profile"
|
|
;;
|
|
|
|
"enable")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
|
|
lock
|
|
updateStatus "$email" 'active'
|
|
syncAll
|
|
echo "Successfully enabled user"
|
|
so-influxdb-manage userenable "$email"
|
|
;;
|
|
|
|
"disable")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
|
|
lock
|
|
updateStatus "$email" 'locked'
|
|
syncAll
|
|
echo "Successfully disabled user"
|
|
so-influxdb-manage userdisable "$email"
|
|
;;
|
|
|
|
"delete")
|
|
verifyEnvironment
|
|
[[ "$email" == "" ]] && fail "Email address must be provided"
|
|
|
|
lock
|
|
deleteUser "$email"
|
|
syncAll
|
|
echo "Successfully deleted user"
|
|
so-influxdb-manage userdel "$email"
|
|
;;
|
|
|
|
"sync")
|
|
lock
|
|
syncAll
|
|
;;
|
|
|
|
"validate")
|
|
validateEmail "$email"
|
|
updatePassword
|
|
echo "Email and password are acceptable"
|
|
;;
|
|
|
|
"valemail")
|
|
validateEmail "$email"
|
|
echo "Email is acceptable"
|
|
;;
|
|
|
|
"valpass")
|
|
updatePassword
|
|
echo "Password is acceptable"
|
|
;;
|
|
|
|
*)
|
|
fail "Unsupported operation: $operation"
|
|
usage
|
|
;;
|
|
esac
|
|
|
|
exit 0
|