Blogging (118)

ChatOps with Mattermost and AWS Lambda

I’ve been working towards making things simpler when managing distributed resources at work. And since we spend most of our day in the chat room (was Slack, now Mattermost) I thought it’s best to get started with ChatOps

It’s just a fancy word for doing stuff right from the chat window. And there’s so much one can do, especially with simple Slash Commands.

Here’s a lambda function I setup yesterday for invalidating CloudFront distributions.

from time import time
import boto3

import json
import os
import re

EXPECTED_TOKEN = os.environ['mmToken']
ALLOWED_USERS = re.split('[, ]', os.environ['allowedUsers'])
    'site-name': 'DISTRIBUTIONID',

def parse_command_text(command_text):
    pattern = r"({})\s+(.*)".format('|'.join(DISTRIBUTIONS.keys()))
    m = re.match(pattern, command_text)
    if m:
        return { 'site':, 'path': path}
        return False

def lambda_handler(event, context):
    # Parse the request
        request_data = event["queryStringParameters"]
        return {
            "statusCode": 400,
            "headers": {"Content-Type": "application/json"},
            "body": '{ "message": "Use GET for setting up mattermost slash command" }'

    # Check the token matches.
    if request_data.get("token", "") != EXPECTED_TOKEN:
        print('Wrong Token!')
        return {
            "statusCode": 401,
            "headers": {"Content-Type": "application/json"},
            "body": '{ "message": "Mattermost token does not match" }'
    # Check the user is allowed to run the command
    if request_data.get("user_name", "") not in ALLOWED_USERS:
        print('Wrong User! {} not in {}'.format(request_data['user_name'], ALLOWED_USERS))
        return {
            "statusCode": 401,
            "headers": {"Content-Type": "application/json"},
            "body": '{ "message": "User not allowed to perform action" }'

    # parse the command
    command_text = request_data.get("text", "")
    if not command_text:
        print('Nothing to do, bailing out')
        return {
            "statusCode": 404,
            "headers": {"Content-Type": "application/json"},
            "body": '{ "message": "No command text sent" }'
    parts = parse_command_text(command_text)
    if not parts: 
        print('Bad formatting - command: {}'.format(command_text))
        return {
            "statusCode": 402,
            "headers": {"Content-Type": "application/json"},
            "body": '{ "message": "Wrong pattern" }'

    # Do the actual work
    cf_client = boto3.client('cloudfront')

    # Invalidate
    boto_response = cf_client.create_invalidation(
            'Paths': {
                'Quantity': len(parts['path']),
                'Items': parts['path'] 
            'CallerReference': str(time()).replace(".", "")

    # Build the response message text.
    text = """##### Executing invalidation
| Key | Info |
| --- | ---- |
| Site | {} |
| Path | {} |
| ID | {} |
| Status | {} |""".format(

    # Build the response object.
    response = {
        "response_type": "in_channel",
        "text": text,

    # Return the response as JSON
    return {
        "body": json.dumps(response),
        "headers": {"Content-Type": "application/json"},
        "statusCode": 200,

Note that you need to hook that up with an API Gateway in AWS. Once that’s done, you will have a URL endpoint ready for deployment.

Next, I created the slash command in mattermost with the following:

slash command configuration

That’s pretty much it. Rinse and repeat for a different command, different usage.

On my list next is to have more interaction with the user in mattermost per
Weekend Project, Yay!

Similar Posts:

Change profiles automatically in Tilix when connecting to SSH hosts

I use Tilix as my main terminal app on Ubuntu. I like it mainly because it’s easy to use and shows multiple sessions in tiles and tabs, so it’s easy to switch between multiple servers without too much fuss

Tilix is also pretty customizable. I just needed to have the “profile” automatically switch according to the server/machine I switch to. This can be done according to the documentation per but I wanted something configured locally, not sent to the remote system.

So I just added a function that wraps my ssh command. Here’s how it looks in my .bashrc

ssh() { 
	SSHAPP=`which ssh`;   
	echo "switching to $ARGS"; 
	printf "\033]7;file://%s/\007" "$ARGS";   

This sets up the hostname of machine you’re logging into as the title. That’s your trigger. What remains is to create a profile and assign that profile to automatically switch when the trigger (hostname:directory, user can also be added) is set.

Go to Profiles > Edit Profile > Advanced (tab) and under Match add the hostname.

That’s about it. I’m going to add a new profile with a RED background now for my production machines! too much?

Update (Jan 8, 2020)

I noticed that I have also added a Match for my localhost hostname in the Default profile, so that the profile would revert to that once I logged off a remote host.

Another thing I needed was to create a special trigger if I wanted to use a wildcard match for hostnames (ie. if I wanted to switch profile on all my AWS instances via Session Manager). And match that special hostname (aws-instance below for example). Here’s my ssh bash function now:

ssh () {
     if [[ $ARGS == i-* ]]
         echo "switching to AWS instance"
         printf "\033]7;file://%s/\007" "aws-instance"
         echo "switching to $ARGS"
         printf "\033]7;file://%s/\007" "$ARGS"

Similar Posts:

Find the owner of an AWS Access Key

This is something you will have to deal with at one time or another after managing AWS IAM users for a while. Basically, it’s straight forward with the following code:

  • Get a list of users
    • for each user get their access key IDs
    • (optional) pipe to grep for checking a specific ID

And here’s the `aws-cli` code

for user in $(aws iam list-users --output text --query 'Users[*].UserName'); do     
  aws iam list-access-keys --user $user --output text; 

# or 
for user in $(aws iam list-users --output text --query 'Users[*].UserName'); do     
  aws iam list-access-keys --user $user --output text | grep $Q_ACCESSKEY 


Similar Posts:


wpid-wp-1425419051162.jpegthis is not a pipe

Similar Posts:

    None Found

All of us cats


Similar Posts:

    None Found

Brewing Beer vs Distilling Spirits

Compare Brewing Beer, Distilling Spirits, & Making Wine

original at

PS. I was actually looking for 🙂

Similar Posts:

    None Found

Casarecce in Ricotta And dried tomato sauce


Similar Posts:

    None Found

Just finished reading Seveneves by Neal Stephenson

Get it from Amazon

Similar Posts:

Where Are They? Fairuz

For some reason whenever I hear this song I have the feeling I’m in a very morbid Doctor Who episode. Here’s my rough translation …

وينن وينن Where are they now?
وين صواتن وين وجوهن وينن Where are their voices, their faces? Where are they?
صار في وادي بيني وبينن There’s a valley between me and them, where are they?
ركبوا عربيات الوقت وهربوا للنسيان They rode the chariots of time and ran away to oblivion
وتركوا ضحكات ولادن منسية ع الحيطان and left the laughs of their children forgotten on the walls
تركولي المفاتيح they left me the keys
تركوا صوت الريح they left me the sound of the wind
وراحوا ما تركوا عنوان but they did not leave an address
عشاق الطرقات أفترقوا لا حكى لا مواعيد the lovers of the road left each other without speaking or appointments
أنا وحدى صوت الشوارع أنا طير القرميد I’m alone am the sound of the streets, I am the bird in the brick roofs
هربت بهالليل من مربط هالخيل I ran away in the night from the horse barn
وأنا قنديل الحزن الوحيد I am the lonely lamp of sorrow…

If you’re interested in more Doctor Who ready setups, check this one: حبيتك تنسيت النوم


Similar Posts:

    None Found

Just discovered kale


fried with mushrooms in an omelet, in a brown baguette

Similar Posts:

    None Found