This PR does a bunch of changes to prepare OnCall for Unified Slack App: 1. Install Slack via Chatops-Proxy. This change contains two parts: getting a Slack install link from chatops-proxy ([code](https://github.com/grafana/oncall/pull/4232/files#diff-437a77d49fc04b92d315651b3df5991000b1ab74cf60aabb21aa77cb2823bf52R46)) and receiving a "slack installed" event from chatops-proxy ([code](https://github.com/grafana/oncall/pull/4232/files#diff-976d106f0962be5c1de5e35582193f68435ed0c17f2defd6bd2857bf6e27f65d)). Also it means that OnCall doesn't need to register slack_links anymore when slack is connected/disconnected. These changes are behind UNIFIED_SLACK_APP_ENABLED flag and should be no-op if flag is not enabled. 2. Get rid of Multiregionatily restrictions - instrument all slack interactions with a ProxyMeta - json data telling chatops-proxy where to route the interaction. Note, that it doesn't apply for "Add to resolution notes" message action - it will be handled differently in following PR. 3. Move all chatops-proxy related stuff from common/oncall-gateway to apps/chatops-proxy Minor changes: 1. Remove usage of **CHATOPS_V3** flag. Chatops v3 is already released (It's a refactoring from previous quarter) --------- Co-authored-by: Vadim Stepanov <vadimkerr@gmail.com> Co-authored-by: Rares Mardare <rares.mardare@grafana.com>
36 lines
834 B
Python
36 lines
834 B
Python
import base64
|
|
import binascii
|
|
import hashlib
|
|
import hmac
|
|
|
|
|
|
def hash(data):
|
|
hasher = hashlib.sha256()
|
|
hasher.update(data)
|
|
return base64.b64encode(hasher.digest()).decode()
|
|
|
|
|
|
def generate_signature(data, secret):
|
|
h = hmac.new(secret.encode(), data.encode(), hashlib.sha256)
|
|
return binascii.hexlify(h.digest()).decode()
|
|
|
|
|
|
def verify_signature(request, secret) -> bool:
|
|
header = request.META.get("HTTP_X_CHATOPS_SIGNATURE")
|
|
if not header:
|
|
return False
|
|
|
|
signatures = header.split(",")
|
|
s = dict(pair.split("=") for pair in signatures)
|
|
t = s.get("t")
|
|
v1 = s.get("v1")
|
|
|
|
payload = request.body
|
|
body_hash = hash(payload)
|
|
string_to_sign = f"{body_hash}:{t}:v1"
|
|
expected = generate_signature(string_to_sign, secret)
|
|
|
|
if expected != v1:
|
|
return False
|
|
|
|
return True
|