Skip to content

Instantly share code, notes, and snippets.

@kurtwheeler
Created September 13, 2013 17:58

Revisions

  1. kurtwheeler created this gist Sep 13, 2013.
    149 changes: 149 additions & 0 deletions publishAmazonSNS.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,149 @@
    #!/bin/bash
    #This script creates a command line tool to publish a notification to Amazon SNS.

    #The second parameter to urllib.quote is very important here.
    #It overrides the default ignore character set which is just '/'
    #If the default is set then the strings will not be url encoded to
    #Amazon's requirements.
    function urlencode {
    python -c "import urllib; print urllib.quote('''$1''', '')"
    }

    usage="Usage: publishAmazonSNS.sh [options...]
    Options:
    -a, --awskey Sets the AWS API Access Key (optional). If not set will read the key from the environment variable $AWSACCESSKEY
    -h, --help This help text
    -k, --awssecretkey Sets the AWS API Secret Access Key (optional). If not set will read the key from the environment variable $AWSSECRETKEY
    -m, --message Specifies the body of the SNS message (required)
    -r, --region Specfies the region of the AWS SNS Topic to publish the message to (required)
    -s, --subject Specifies the subject of the message (optional)
    -t, --topic Specfies the AWS SNS Topic to publish the message to (required)
    -v, --verbose Sets the verbosity level. Each instance of -v adds 1 to verbosity"

    # Reset all variables that might be set
    region=""
    topic=""
    subject=""
    message=""
    AWSKey=$AWSACCESSKEY
    secretAWSKey=$AWSSECRETKEY
    verbose=0

    while :
    do
    case $1 in
    -h | --help | -\?)
    echo "$usage"
    # Call your Help() or usage() function here.
    exit 0 # This is not an error, User asked help. Don't do "exit 1"
    ;;
    -r | --region)
    region=$2
    shift 2
    ;;
    -t | --topic)
    topic=$2
    shift 2
    ;;
    -m | --message)
    message=$2
    shift 2
    ;;
    -s | --subject)
    subject=$2
    shift 2
    ;;
    -a | --awskey)
    AWSKey=$2
    shift 2
    ;;
    -k | --awssecretkey)
    secretAWSKey=$2
    shift 2
    ;;
    -v | --verbose)
    # Each instance of -v adds 1 to verbosity
    verbose=$((verbose+1))
    shift
    ;;
    --) # End of all options
    shift
    break
    ;;
    -*)
    echo "WARN: Unknown option (ignored): $1" >&2
    shift
    ;;
    *) # no more options. Stop while loop
    break
    ;;
    esac
    done

    # Check for required variables
    if [ ! "$region" ]; then
    echo "ERROR: option '--region REGION' not given. See --help" >&2
    exit 1
    fi

    if [ ! "$topic" ]; then
    echo "ERROR: option '--topic TOPIC' not given. See --help" >&2
    exit 1
    fi

    if [ ! "$message" ]; then
    echo "ERROR: option '--message MESSAGE' not given. See --help" >&2
    exit 1
    fi

    if [ ! "$AWSKey" ]; then
    echo "ERROR: neither option '--awskey AWSKEY' given nor environment variable \$AWSACCESSKEY set. See --help" >&2
    exit 1
    fi

    if [ ! "$secretAWSKey" ]; then
    echo "ERROR: neither option '--awssecretkey AWSSECRETKEY' given nor environment variable \$AWSSECRETKEY set. See --help" >&2
    exit 1
    fi

    subjectParam=""
    if [ "$subject" ]; then
    subjectParam="&Subject=$(urlencode "$subject")"
    fi

    timestamp=$(date -Iseconds -u)


    #ORDER MATTERS!!!!!
    #The parameters need to be lexigraphically sorted.
    #This means that capitalization makes a difference.
    paramString="AWSAccessKeyId=$(urlencode "$AWSKey")\
    &Action=Publish\
    &Message=$(urlencode "$message")\
    &SignatureMethod=HmacSHA256\
    &SignatureVersion=2\
    $subectParam\
    &Timestamp=$(urlencode "$timestamp")\
    &TopicArn=$(urlencode "$topic")\
    &Version=2010-03-31"

    if [ $verbose -ge 1 ]; then
    echo "INFO: Query parameters: $paramString"
    fi

    stringToSign="POST
    sns.$region.amazonaws.com
    /
    $paramString"

    signature=$(echo -n "$stringToSign" | openssl dgst -sha256 -hmac "$secretAWSKey" -binary | base64)
    encoded=$(urlencode "$signature")

    fullParams="$paramString&Signature=$encoded"

    curlVerbose=""
    if [ $verbose -ge 2 ]; then
    curlVerbose="-v"
    fi

    curl $curlVerbose -d "$fullParams" "http://sns.$region.amazonaws.com"