#!/usr/bin/env bash

ERROR=''
KNOWN_EVENTS='modules sva registration supa-update-status av aph fw avc uc dp sva-load task-status exchange-malware network-sandboxing adcloud exchange-user-credentials hd antiexploit network-monitor endpoint-moved-in endpoint-moved-out hwid-change install new-incident ransomware-mitigation security-container-update-available troubleshooting-activity uninstall'

GZ_URL=''
API_KEY=''
SERVICE_TYPE=''
SERVICE_URL=''
SPLUNK_TOKEN=''
REQUIRE_VALID_SSL_CERT='false'
SPLUNK_HOST_PREFIX=''
SPLUNK_PORT=''
ENABLE_EVENTS=''
DISABLE_EVENTS=''

function usage(){
        cat <<USAGE-MESSAGE
How to use this script:
    ./bdpusheventconfig.sh -g <console_url> -k <api_key> -t <service_type> -u <service_url> -a <auth_token> -v -c <events>

Options:
    -g console_url          Gravity Zone API url
    -k api_key              Gravity Zone API key
    -t service_type         Service type: splunk, jsonRPC or cef
    -u service_url          Splunk, RPC or CEF url
    -a auth_token           Authorization token
    -v                      Verify service SSL certificate
    -c                      Connect to Splunk Cloud free trials. Adds 'input-' to the service host and uses port 8088 (if port is not specified).
    -d                      Connect to Splunk Cloud instances. Adds 'http-inputs-' to the service host and uses port 443 (if port is not specified).
    -h, --help              Usage help
    
The <events> variable refers to one event or to a space-separated list of events to subscribe to. 

Events:
    $KNOWN_EVENTS
    
To subscribe to all events, use the value 'all' or specify each one of them. If the events list is empty (with no event specified) then the integration is disabled.

Examples:

    Enable Splunk integration
    ./bdpusheventconfig.sh -g https://gz.example.com/api/v1.0/jsonrpc/push -k abcdefghijklmnopqrstuvwxyz123456 -t splunk -u https://splunk.example.com -a 11111111-2222-3333-4444-555555555555 -c $KNOWN_EVENTS

    Configure a json RPC service
    ./bdpusheventconfig.sh -g https://gz.example.com/api/v1.0/jsonrpc/push -k abcdefghijklmnopqrstuvwxyz123456 -t jsonRPC -u https://rpc.example.com $KNOWN_EVENTS

    Disable Splunk integration
    ./bdpusheventconfig.sh -g https://gz.example.com/api/v1.0/jsonrpc/push -k abcdefghijklmnopqrstuvwxyz123456 -t splunk -u https://splunk.example.com -a 11111111-2222-3333-4444-555555555555 -c
    
USAGE-MESSAGE
}

#####
# check dependencies
#####

# check base64
BASE64=$(which base64)

if [ "$?" -ne 0 ]; then
    echo 'base64 is not available'
    exit 10 # base64 is not available
fi

# check curl
CURL=$(which curl)

if [ "$?" -ne 0 ]; then
    echo 'curl is not available'
    exit 11 # curl is not available
fi

#####
# check parameters
#####

while getopts ':g:k:t:u:a:vcdh' OPT; do
    case "$OPT" in

        # dispaly usage
        h)
            usage
            exit 0
            ;;

        # get gz api url
        g)
            GZ_URL="$OPTARG"
            ;;

        # get api key
        k)
            API_KEY="$OPTARG"
            ;;

        # get service type
        t)
            SERVICE_TYPE="$OPTARG"
            ;;

        # get service_url
        u)
            SERVICE_URL="$OPTARG"
            ;;

        # get authorization auth token
        a)
            AUTHORIZATION_TOKEN="$OPTARG"
            ;;

        # verify Splunk SSL certificate
        v)
            REQUIRE_VALID_SSL_CERT='true'
            ;;

        # connect to Splunk Cloud free trial
        c) 
            SPLUNK_HOST_PREFIX='input-'
            SPLUNK_PORT='8088'
            ;;

        # connect to Splunk Cloud
        d) 
            SPLUNK_HOST_PREFIX='http-inputs-'
            ;;

    esac

done

# shift read options
shift $((OPTIND-1))

# search for events to enalbe
for EVENT in $@; do
    if [ "$EVENT" == '--help' ]; then
        usage

        exit 0
    fi

    if [ "$EVENT" == 'all' ]; then
        ENABLE_EVENTS=$KNOWN_EVENTS

        break
    fi

    for KNOWN_EVENT in $KNOWN_EVENTS; do

        if [ "$EVENT" == "$KNOWN_EVENT" ]; then
            if [ ! -z "$ENABLE_EVENTS" ]; then
                ENABLE_EVENTS="$ENABLE_EVENTS "
            fi

            ENABLE_EVENTS="$ENABLE_EVENTS$EVENT"

            break
        fi

    done

done

# get events to disable
for KNOWN_EVENT in $KNOWN_EVENTS; do

    KNOWN_EVENT_FOUND='false'

    for EVENT in $ENABLE_EVENTS; do

        if [ "$KNOWN_EVENT" == "$EVENT" ]; then

            KNOWN_EVENT_FOUND='true'

            break
        fi

    done

    if [ "$KNOWN_EVENT_FOUND" == 'true' ]; then

        continue
    fi

    if [ ! -z "$DISABLE_EVENTS" ]; then
        DISABLE_EVENTS="$DISABLE_EVENTS "
    fi

    DISABLE_EVENTS="$DISABLE_EVENTS$KNOWN_EVENT"

done

#####
# validate parameters
#####

while $(exit 0); do
    if [ -z "$GZ_URL" ]; then
        ERROR='Gravity Zone API url not set. Set the Gravity Zone API url with -g url.'

        break
    fi

    if [ -z "$API_KEY" ]; then
        ERROR='Gravity Zone API key not set. Set the Gravity Zone API key with -k key.'

        break
    fi

    if [ -z "$SERVICE_TYPE" ]; then
        ERROR='Service type not set. Set the service type with -t service_type.'

        break
    fi

    if [ "$SERVICE_TYPE" != 'jsonRPC' -a "$SERVICE_TYPE" != 'splunk' -a "$SERVICE_TYPE" != 'cef' ]; then
        ERROR="Unknown service type: $SERVICE_TYPE."

        break
    fi

    if [ -z "$SERVICE_URL" ]; then
        ERROR='Service url not set. Set the service url with -u url.'

        break
    fi

    if [ "$SERVICE_TYPE" == 'jsonRPC' -o "$SERVICE_TYPE" == 'splunk' -o "$SERVICE_TYPE" == 'cef' ]; then
        if [ -z "$AUTHORIZATION_TOKEN" ]; then
            ERROR='Authorization token not set. Set the authorization token with -a token.'

            break
        fi
    fi

    break
done

# echo usage on param error
if [ ! -z "$ERROR" ]; then
    echo "Error: $ERROR"

    echo
    usage

    exit 12 # input validation error
fi

#####
# prepare parameters
#####

# encode the GZ API auth header
REQUEST_HEADER_VALUE=$(echo -n "$API_KEY:" | $BASE64 -w 0)

# add protocol to SERVICE_URL if missing
if echo "$SERVICE_URL" | grep -vP '^https?://' 1>/dev/null 2>&1; then
    SERVICE_URL="https://$SERVICE_URL"
fi

# prepare authorization token json fragment
AUTHORIZATION_TOKEN_JSON=''

case $SERVICE_TYPE in

    'splunk')

        if [ ! -z "$SPLUNK_HOST_PREFIX" ]; then
            # prepare Splunk url: input-[SPLUNK_CLOUD_URL]:8088/services/collector
            SERVICE_URL=$(echo "$SERVICE_URL" | sed -r "s/^(https?:\/\/)(.+)?/\1$SPLUNK_HOST_PREFIX\2/")
        fi

        if [ ! -z "$SPLUNK_PORT" ]; then

            # add Splunk default port if missing
            if echo "$SERVICE_URL" | grep -vP ':[0-9]+$' 1>/dev/null 2>&1; then
                SERVICE_URL="$SERVICE_URL:$SPLUNK_PORT";
            fi

        fi

        SERVICE_URL="$SERVICE_URL/services/collector";

        # prepare Splunk auth token: Splunk [AUTHORIZATION_TOKEN]
        AUTHORIZATION_TOKEN="Splunk $AUTHORIZATION_TOKEN"
        AUTHORIZATION_TOKEN_JSON=', "splunkAuthorization": "'"$AUTHORIZATION_TOKEN"'"'
    ;;

    'jsonRPC' | 'cef')
        # prepare auth token json
        AUTHORIZATION_TOKEN_JSON=', "authorization": "'"$AUTHORIZATION_TOKEN"'"'
    ;;

    *)
        AUTHORIZATION_TOKEN=''
    ;;

esac

# prepare events json
EVENTS_JSON=''

for EVENT in $ENABLE_EVENTS; do
    if [ ! -z "$EVENTS_JSON" ]; then
        EVENTS_JSON="$EVENTS_JSON, "
    fi

    EVENTS_JSON="$EVENTS_JSON\"$EVENT\": true"
done

for EVENT in $DISABLE_EVENTS; do
    if [ ! -z "$EVENTS_JSON" ]; then
        EVENTS_JSON="$EVENTS_JSON, "
    fi

    EVENTS_JSON="$EVENTS_JSON\"$EVENT\": false"
done

EVENTS_JSON="{$EVENTS_JSON}"

#####
# review parameters
#####

echo "Gravity Zone API url:         $GZ_URL"
echo "Gravity Zone API key:         $API_KEY"
echo "Service type:                 $SERVICE_TYPE"
echo "Service url:                  $SERVICE_URL"
echo "Authorization header:         $AUTHORIZATION_TOKEN"
echo "Enabling events:              $ENABLE_EVENTS"
echo "Disabling events:             $DISABLE_EVENTS"

#####
# send request
#####

echo
echo -e "Sending request ..."

# send the Event Push Service API call
RESULT=$("$CURL" --tlsv1.2 -sS -k -X POST \
"$GZ_URL" \
-H 'authorization: Basic '"$REQUEST_HEADER_VALUE" \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{"params": {"status": 1, "serviceType": "'"$SERVICE_TYPE"'", "serviceSettings": {"url": "'"$SERVICE_URL"'", "requireValidSslCertificate": '"$REQUIRE_VALID_SSL_CERT""$AUTHORIZATION_TOKEN_JSON"'}, "subscribeToEventTypes": '"$EVENTS_JSON"'}, "jsonrpc": "2.0", "method": "setPushEventSettings", "id": "1"}' 2>&1)

# check curl exit code
if [ $? -ne 0 ]; then
    echo "Error sending request: $RESULT"
    exit 13 # curl failure
fi

# print result
if echo "$RESULT" | grep -P '"result"\s*:\s*true' 1>/dev/null 2>&1; then
    echo -e "SUCCESS - server response:\n$RESULT"
else
    echo -e "FAIL - server response:\n$RESULT"
    exit 14 # server returned an error
fi
