Update to latest kratos; add support for a custom status trait to represent whether a user is locked or not; refactor so-user to use new enable/disable capabilities in SOC; remove 'delete' option from so-user usage to avoid having user lists out of sync across SOC and external apps

This commit is contained in:
Jason Ertel
2020-09-04 17:01:45 -04:00
parent 351e7761ef
commit f27e5164d0
8 changed files with 129 additions and 85 deletions

View File

@@ -48,6 +48,7 @@ if [[ "$resp" =~ \"status\":\"Ok\" ]]; then
echo "Successfully added user to Cortex." echo "Successfully added user to Cortex."
else else
echo "Unable to add user to Cortex; user might already exist." echo "Unable to add user to Cortex; user might already exist."
echo $resp
exit 2 exit 2
fi fi

View File

@@ -51,6 +51,7 @@ if [[ "$resp" =~ \"status\":\"Locked\" || "$resp" =~ \"status\":\"Ok\" ]]; then
echo "Successfully updated user in Cortex." echo "Successfully updated user in Cortex."
else else
echo "Failed to update user in Cortex." echo "Failed to update user in Cortex."
echo $resp
exit 2 exit 2
fi fi

View File

@@ -54,5 +54,6 @@ if [[ $? -eq 0 ]]; then
echo "Successfully added user to Fleet." echo "Successfully added user to Fleet."
else else
echo "Unable to add user to Fleet; user might already exist." echo "Unable to add user to Fleet; user might already exist."
echo $resp
exit 2 exit 2
fi fi

View File

@@ -53,5 +53,6 @@ if [[ $? -eq 0 ]]; then
echo "Successfully updated user in Fleet." echo "Successfully updated user in Fleet."
else else
echo "Failed to update user in Fleet." echo "Failed to update user in Fleet."
echo $resp
exit 2 exit 2
fi fi

View File

@@ -47,5 +47,6 @@ if [[ "$resp" =~ \"status\":\"Ok\" ]]; then
echo "Successfully added user to TheHive." echo "Successfully added user to TheHive."
else else
echo "Unable to add user to TheHive; user might already exist." echo "Unable to add user to TheHive; user might already exist."
echo $resp
exit 2 exit 2
fi fi

View File

@@ -11,12 +11,13 @@
. /usr/sbin/so-common . /usr/sbin/so-common
if [[ $# < 1 || $# > 2 ]]; then if [[ $# < 1 || $# > 2 ]]; then
echo "Usage: $0 <list|add|update|delete|validate|valemail|valpass> [email]" echo "Usage: $0 <list|add|update|enable|disable|validate|valemail|valpass> [email]"
echo "" echo ""
echo " list: Lists all user email addresses currently defined in the identity system" echo " list: Lists all user email addresses currently defined in the identity system"
echo " add: Adds a new user to the identity system; requires 'email' parameter" echo " add: Adds a new user to the identity system; requires 'email' parameter"
echo " update: Updates a user's password; requires 'email' parameter" echo " update: Updates a user's password; requires 'email' parameter"
echo " delete: Deletes an existing user; requires 'email' parameter" echo " enable: Enables a user; requires 'email' parameter"
echo " disable: Disables a user; requires 'email' parameter"
echo " validate: Validates that the given email address and password are acceptable for defining a new user; requires 'email' parameter" echo " validate: Validates that the given email address and password are acceptable for defining a new user; requires 'email' parameter"
echo " valemail: Validates that the given email address is acceptable for defining a new user; requires 'email' parameter" echo " valemail: Validates that the given email address is acceptable for defining a new user; requires 'email' parameter"
echo " valpass: Validates that a password is acceptable for defining a new user" echo " valpass: Validates that a password is acceptable for defining a new user"
@@ -63,7 +64,7 @@ function findIdByEmail() {
email=$1 email=$1
response=$(curl -Ss ${kratosUrl}/identities) response=$(curl -Ss ${kratosUrl}/identities)
identityId=$(echo "${response}" | jq ".[] | select(.addresses[0].value == \"$email\") | .id") identityId=$(echo "${response}" | jq ".[] | select(.verifiable_addresses[0].value == \"$email\") | .id")
echo $identityId echo $identityId
} }
@@ -113,7 +114,7 @@ function listUsers() {
response=$(curl -Ss ${kratosUrl}/identities) response=$(curl -Ss ${kratosUrl}/identities)
[[ $? != 0 ]] && fail "Unable to communicate with Kratos" [[ $? != 0 ]] && fail "Unable to communicate with Kratos"
echo "${response}" | jq -r ".[] | .addresses[0].value" | sort echo "${response}" | jq -r ".[] | .verifiable_addresses[0].value" | sort
} }
function createUser() { function createUser() {
@@ -122,17 +123,8 @@ function createUser() {
now=$(date -u +%FT%TZ) now=$(date -u +%FT%TZ)
addUserJson=$(cat <<EOF 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": {"email":"${email}"},
"traits_schema_id": "default" "schema_id": "default"
} }
EOF EOF
) )
@@ -152,6 +144,36 @@ EOF
updatePassword $identityId updatePassword $identityId
} }
function updateStatus() {
email=$1
status=$2
identityId=$(findIdByEmail "$email")
[[ ${identityId} == "" ]] && fail "User not found"
response=$(curl -Ss "${kratosUrl}/identities/$identityId")
[[ $? != 0 ]] && fail "Unable to communicate with Kratos"
oldConfig=$(echo "select config from identity_credentials where identity_id=${identityId};" | sqlite3 "$databasePath")
if [[ "$status" == "locked" ]]; then
config=$(echo $oldConfig | sed -e 's/hashed/locked/')
echo "update identity_credentials set config=CAST('${config}' as BLOB) where identity_id=${identityId};" | sqlite3 "$databasePath"
[[ $? != 0 ]] && fail "Unable to lock credential record"
echo "delete from sessions where identity_id=${identityId};" | sqlite3 "$databasePath"
[[ $? != 0 ]] && fail "Unable to invalidate sessions"
else
config=$(echo $oldConfig | sed -e 's/locked/hashed/')
echo "update identity_credentials set config=CAST('${config}' as BLOB) where identity_id=${identityId};" | sqlite3 "$databasePath"
[[ $? != 0 ]] && fail "Unable to unlock credential record"
fi
updatedJson=$(echo "$response" | jq ".traits.status = \"$status\" | del(.verifiable_addresses) | del(.id) | del(.schema_url)")
response=$(curl -Ss -XPUT ${kratosUrl}/identities/$identityId -d "$updatedJson")
[[ $? != 0 ]] && fail "Unable to mark user as locked"
}
function updateUser() { function updateUser() {
email=$1 email=$1
@@ -179,9 +201,9 @@ case "${operation}" in
validateEmail "$email" validateEmail "$email"
createUser "$email" createUser "$email"
echo "Successfully added new user to SOC" echo "Successfully added new user to SOC"
check_container thehive && (echo $password | so-thehive-user-add "$email" || so-thehive-user-enable "$email" true) check_container thehive && echo $password | so-thehive-user-add "$email"
check_container cortex && (echo $password | so-cortex-user-add "$email" || so-cortex-user-enable "$email" true) check_container cortex && echo $password | so-cortex-user-add "$email"
check_container fleet && (echo $password | so-fleet-user-add "$email" || so-fleet-user-enable "$email" true) check_container fleet && echo $password | so-fleet-user-add "$email"
;; ;;
"list") "list")
@@ -197,6 +219,28 @@ case "${operation}" in
echo "Successfully updated user" echo "Successfully updated user"
;; ;;
"enable")
verifyEnvironment
[[ "$email" == "" ]] && fail "Email address must be provided"
updateStatus "$email" 'active'
echo "Successfully enabled user"
check_container thehive && so-thehive-user-enable "$email" true
check_container cortex && so-cortex-user-enable "$email" true
check_container fleet && so-fleet-user-enable "$email" true
;;
"disable")
verifyEnvironment
[[ "$email" == "" ]] && fail "Email address must be provided"
updateStatus "$email" 'locked'
echo "Successfully disabled user"
check_container thehive && so-thehive-user-enable "$email" false
check_container cortex && so-cortex-user-enable "$email" false
check_container fleet && so-fleet-user-enable "$email" false
;;
"delete") "delete")
verifyEnvironment verifyEnvironment
[[ "$email" == "" ]] && fail "Email address must be provided" [[ "$email" == "" ]] && fail "Email address must be provided"

View File

@@ -6,52 +6,39 @@ selfservice:
password: password:
enabled: true enabled: true
flows:
settings: settings:
privileged_session_max_age: 1m ui_url: https://{{ WEBACCESS }}/?r=/settings
after:
profile:
hooks:
- hook: verify
verify: verification:
return_to: https://{{ WEBACCESS }}/ ui_url: https://{{ WEBACCESS }}/
logout:
redirect_to: https://{{ WEBACCESS }}/login/
login: login:
request_lifespan: 10m ui_url: https://{{ WEBACCESS }}/login/
error:
ui_url: https://{{ WEBACCESS }}/login/
registration: registration:
request_lifespan: 10m ui_url: https://{{ WEBACCESS }}/login/
after:
password: default_browser_return_url: https://{{ WEBACCESS }}/
hooks: whitelisted_return_urls:
- hook: session - http://127.0.0.1
- hook: verify
log: log:
level: debug level: debug
format: json format: json
secrets: secrets:
session: default:
- {{ KRATOSKEY }} - {{ KRATOSKEY }}
urls: serve:
login_ui: https://{{ WEBACCESS }}/login/ public:
registration_ui: https://{{ WEBACCESS }}/login/ base_url: https://{{ WEBACCESS }}/auth/
error_ui: https://{{ WEBACCESS }}/login/ admin:
settings_ui: https://{{ WEBACCESS }}/?r=/settings base_url: https://{{ WEBACCESS }}/kratos/
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_urls:
- http://127.0.0.1
hashers: hashers:
argon2: argon2:
@@ -62,7 +49,6 @@ hashers:
key_length: 32 key_length: 32
identity: identity:
traits:
default_schema_url: file:///kratos-conf/schema.json default_schema_url: file:///kratos-conf/schema.json
courier: courier:

View File

@@ -2,6 +2,9 @@
"$id": "securityonion.schema.json", "$id": "securityonion.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"title": "Person", "title": "Person",
"type": "object",
"properties": {
"traits": {
"type": "object", "type": "object",
"properties": { "properties": {
"email": { "email": {
@@ -31,6 +34,10 @@
"role": { "role": {
"type": "string", "type": "string",
"title": "Role" "title": "Role"
},
"status": {
"type": "string",
"title": "Status"
} }
}, },
"required": [ "required": [
@@ -38,3 +45,5 @@
], ],
"additionalProperties": false "additionalProperties": false
} }
}
}