diff options
author | Aravinda VK <avishwan@redhat.com> | 2017-09-18 14:34:54 +0530 |
---|---|---|
committer | Aravinda VK <avishwan@redhat.com> | 2017-10-13 11:17:39 +0000 |
commit | add7116efa1f31e86f9c00c72c71872b1161370f (patch) | |
tree | 985b495eda9fd698d2eda1982c4013301bc6c4ef /events/src/utils.py | |
parent | 3dce15e10c263e8e071b26046568e0a171a3153d (diff) |
eventsapi: Add JWT signing support
New argument added to accept secret to generate JWT token. This patch
does not affect the backward compatibility.
Usage:
gluster-eventsapi webhook-add <url> [-t <TOKEN>] \
[-s SECRET]
With `--token` argument, Token header will be added as is.
Authorization: Bearer <TOKEN>
In case of shared secret, Gluster will generate JWT token using the
secret and then add it to Authorization header.
Authorization: Bearer <GENERATED_TOKEN>
Secret/Token can be updated using `webhook-mod` command.
Generated token will include the following payload,
{
"iss": "gluster",
"exp": EXPIRY_TIME,
"sub": EVENT_TYPE,
"iat": EVENT_TIME
}
Where: iss - Issuer, exp - Expiry Time, sub - Event Type
used as Subject, iat - Event Time used as Issue Time
BUG: 1496363
Change-Id: Ib6b6fab23fb212d7f5e9bbc9e1416a9e9813ab1b
Signed-off-by: Aravinda VK <avishwan@redhat.com>
Diffstat (limited to 'events/src/utils.py')
-rw-r--r-- | events/src/utils.py | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/events/src/utils.py b/events/src/utils.py index 2a77b13d502..5130720d529 100644 --- a/events/src/utils.py +++ b/events/src/utils.py @@ -13,10 +13,11 @@ import json import os import logging import fcntl -from errno import ESRCH, EBADF +from errno import EBADF from threading import Thread import multiprocessing from Queue import Queue +from datetime import datetime, timedelta from eventsapiconf import (LOG_FILE, WEBHOOKS_FILE, @@ -183,15 +184,33 @@ def autoload_webhooks(): load_webhooks() -def publish_to_webhook(url, token, message_queue): +def get_jwt_token(secret, event_type, event_ts, jwt_expiry_time_seconds=60): + import jwt + payload = { + "exp": datetime.utcnow() + timedelta(seconds=jwt_expiry_time_seconds), + "iss": "gluster", + "sub": event_type, + "iat": event_ts + } + return jwt.encode(payload, secret, algorithm='HS256') + + +def publish_to_webhook(url, token, secret, message_queue): # Import requests here since not used in any other place import requests http_headers = {"Content-Type": "application/json"} while True: - message_json = message_queue.get() + hashval = "" + event_type, event_ts, message_json = message_queue.get() if token != "" and token is not None: - http_headers["Authorization"] = "Bearer " + token + hashval = token + + if secret != "" and secret is not None: + hashval = get_jwt_token(secret, event_type, event_ts) + + if hashval: + http_headers["Authorization"] = "Bearer " + hashval try: resp = requests.post(url, headers=http_headers, data=message_json) @@ -218,7 +237,7 @@ def publish_to_webhook(url, token, message_queue): def plugin_webhook(message): message_json = json.dumps(message, sort_keys=True) logger.debug("EVENT: {0}".format(message_json)) - webhooks_pool.send(message_json) + webhooks_pool.send(message["event"], message["ts"], message_json) class LockedOpen(object): @@ -298,9 +317,17 @@ class PidFile(object): def webhook_monitor(proc_queue, webhooks): queues = {} - for url, token in webhooks.items(): + for url, data in webhooks.items(): + if isinstance(data, str) or isinstance(data, unicode): + token = data + secret = None + else: + token = data["token"] + secret = data["secret"] + queues[url] = Queue() - t = Thread(target=publish_to_webhook, args=(url, token, queues[url])) + t = Thread(target=publish_to_webhook, args=(url, token, secret, + queues[url])) t.start() # Get the message sent to Process queue and distribute to all thread queues @@ -329,8 +356,8 @@ class WebhookThreadPool(object): self.proc.terminate() self.start() - def send(self, message): - self.queue.put(message) + def send(self, event_type, event_ts, message): + self.queue.put((event_type, event_ts, message)) def init_webhook_pool(): |