-
Notifications
You must be signed in to change notification settings - Fork 8
/
lambda_function.py
110 lines (81 loc) · 3.28 KB
/
lambda_function.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# -*- encoding: utf-8 -*-
from __future__ import unicode_literals, division, print_function,\
absolute_import
from nizkctf.settings import Settings
from nizkctf.subrepo import SubRepo
from nizkctf.repohost import RepoHost
from nizkctf.proposal import consider_proposal
from nizkctf.six import to_bytes
import os
import json
import base64
import tempfile
import traceback
def run(merge_info):
SubRepo.set_clone_into(tempfile.mkdtemp())
# Prepare git and ssh for usage inside the container
setup_environment()
# Merge proposal if changes are valid
consider_proposal(merge_info)
def handle_payload(payload, context):
merge_info = RepoHost.webhook.adapt_payload(payload)
if not merge_info:
# Message not of our interest (e.g. merge request closed)
return
try:
run(merge_info)
except:
# Do not re-raise, we do not want automatic retries
traceback.print_exc()
# Send tracking number to the user
send_cloudwatch_info(merge_info, context)
def send_cloudwatch_info(merge_info, context):
proj = Settings.submissions_project
mr_id = merge_info['mr_id']
comment = "Sorry. A failure has occurred when processing your proposal. " \
"Please contact support and present the following info:\n\n" \
"**Stream name**: %s\n" \
"**Request ID**: %s\n" % \
(context.log_stream_name, context.aws_request_id)
repohost = RepoHost.instance()
repohost.mr_comment(proj, mr_id, comment)
repohost.mr_close(proj, mr_id)
def handle_apigw(event, context):
headers = event['params']['header']
raw_payload = event['body']
# autenticate the message
secret = to_bytes(os.getenv('WEBHOOK_SECRET_TOKEN'))
RepoHost.webhook.auth(secret, headers, to_bytes(raw_payload))
payload = json.loads(raw_payload)
return handle_payload(payload, context)
def handle_sns(event, context):
raw_payload = event['Records'][0]['Sns']['Message']
payload = json.loads(raw_payload)
# no way to authenticate, but also no need to
# (publishing to the SNS topic should already be authenticated)
return handle_payload(payload, context)
def setup_environment():
root = os.getenv('LAMBDA_TASK_ROOT')
bin_dir = os.path.join(root, 'bin')
os.environ['PATH'] += ':' + bin_dir
os.environ['GIT_EXEC_PATH'] = bin_dir
ssh_dir = tempfile.mkdtemp()
ssh_identity = os.path.join(ssh_dir, 'identity')
with os.fdopen(os.open(ssh_identity, os.O_WRONLY | os.O_CREAT, 0o600),
'w') as f:
f.write(base64.b64decode(os.getenv('SSH_IDENTITY')))
ssh_config = os.path.join(ssh_dir, 'config')
with open(ssh_config, 'w') as f:
f.write('CheckHostIP no\n'
'StrictHostKeyChecking yes\n'
'IdentityFile %s\n'
'UserKnownHostsFile %s\n' %
(ssh_identity, os.path.join(root, 'known_hosts')))
os.environ['GIT_SSH_COMMAND'] = 'ssh -F %s' % ssh_config
def lambda_handler(event, context):
if 'Records' in event:
return handle_sns(event, context)
elif 'body' in event:
return handle_apigw(event, context)
raise ValueError("Did not recognize a valid event originated by SNS nor "
"by API Gateway. Did you configure it correctly?")