Posts about gotify

Authentik Gotifiy Login Notifications

SSO all the things

Continuing with my journy of utilising Authentik for my SSO. After reading a rather good comment by /u/internallogictv over on the reddit /r/selfhosted, I wanted to add a few more protections. The simplest of which is to send myself a notification whenever a login or a failed login occurs.

Step 1

First things first we create a new application in gotify in order to generate a token for authentik use. Select the Apps tab and press the Create Application button.

Gotify create an application

Step 2

Create a new gotify property mapping in the Admin Interface -> Customisation -> Property Mappings.

I've built this so a login failed is set to the maximum gotify priority level regardless of the user group. For successful logins I divide the levels based on the group gotify-users. I algo create a geo uri for mapping applications on android. You will be able to click the notification and it will open the city co-ordinates, although you may have to skip this if you don't have the geoipupdate container configured.

try:
    # Get the login failed username
    event_user = notification.event.context["username"]
except:
    # Get the login succeeded username
    event_user = notification.event.user["username"]

if notification.event.action == "login_failed":
    priority = 7
    severity = "warning"
elif ak_is_group_member( ak_user_by(username=event_user), name="gotify-users" ): # Check if the user belongs to group
    priority = 1
    severity = notification.severity
else: # default notification settings
    priority = 0
    severity = notification.severity

# Build a geo uri for opening a mapping applications from the gotify notification.
geo_uri = f"geo:{notification.event.context['geo']['lat']},{notification.event.context['geo']['long']}?q={notification.event.context['geo']['lat']},{notification.event.context['geo']['long']}"

title = f"{severity} from authentik {notification.event.action.replace('_', ' ')}".capitalize()

message = f"New {notification.event.action.replace('_', ' ')} for {event_user} was detected coming from {notification.event.context['geo']['city']} {notification.event.context['geo']['country']} from the IP address: {str(notification.event.client_ip)}".capitalize()

# Build the gotify payload
gotify_payload = {
    "title": title,
    "message": message,
    "priority": priority,
    "extras": { "client::notification": { "click": { "url": geo_uri } }},
}

return gotify_payload

Step 3

Create a new notification transport Admin Interface -> Events -> Notification Transports using Webhook (generic) your gotify message url with the token created in step one https://example.tld/gotify/message?token=yourtokenhere

Step 4

Finally we create the notification rule that actually calls the Notification transport. Admin Interface -> Events -> Notification Rules Create a new rule login-notification sending to the group of your choice (This dosn't really matter but it will display an ugly json string as notification on the web UI). Select the Gotify notification transport you created and set the Severity to Notice.

Now we have to create the policies authentik-core-login and authentik-core-login-failed to the event. Expand the login-notification event and press Create Policy. Select Event Matcher Policy, name it authentik-core-login enable the Execution Logging option, select the Login action and authentik Core App. Finish and repeat for the Login Failed action.

Now you should be receiving Login and Login Failed notifications from your Authentik instance over Gotify. I Hope I'll be able to update this to pull different tokens from the user/group attributes in the future to better separate notifications to individual users/admins.


SSH Login Notifications with Gotify

Gotify is a simple server for sending and receiving messages

Inspired by this post I decided to add a notification on my phone every time an ssh session began on my servers. Seeing as I make use of Gotify for selfhosted push notifications I used that rather than signal.

First I created created the file /usr/local/bin/sshnotif. At the top you can add your own token and Gotify url

Update: I had to push the current time back a full minute in order to improve consistency. I'll defiantly want to revisit this at a later date

#!/bin/bash

exec &> /dev/null #Hide output

Gotify_URL='https://example.tld/gotify'
Gotify_Token='gotify-app-token'

notify()
{

        now=$(date -d "-60 seconds" +%s) #Get current time minus 60 seconds
        end=$((SECONDS+30)) #Set 30s Timeout for loop

        while [ $SECONDS -lt $end ]; do

                SSHdate=$(date -d "$(who |grep pts|tail -1 | awk '{print $3, $4}')" +%s) #Check for the latest SSH session

                if [ $SSHdate -ge $now ]; then #Once who is updated continue with sending Notification

                        title="SSH Login for $(/bin/hostname -f)"
                        message="$(/usr/bin/who | grep pts)"

                        /usr/bin/curl -X POST -s \
                                -F "title=${title}" \
                                -F "message=${message}" \
                                -F "priority=5" \
                                "${Gotify_URL}/message?token=${Gotify_Token}"

                        break
                fi
        done

}

notify & #Run in background to prevent holding up the login process

Run the command chmod +x /usr/local/bin/sshnotif

In the file /etc/pam.d/sshd add the following line

# note optional is set to prevent ssh login failure
session optional pam_exec.so /usr/local/bin/sshnotif

I now get a nice notification with all the open SSH sessions listed. Unlike the post on 8192.one I didn't want any IP address resolution using an online service. I plan on integrating the MaxMind GeoLite2 database at some point. However as I already have Graylog set up to do this it's not a high priority for me.

Thanks for the shoutout: https://zerosec.xyz/posts/gotify-notifications/