|
#!/usr/bin/env python |
|
import re |
|
|
|
from troposphere import GetAtt, Join, Ref |
|
from troposphere import Parameter, Output, Template |
|
from troposphere import AWS_REGION |
|
|
|
import troposphere.awslambda as awslambda |
|
import troposphere.iam as iam |
|
import troposphere.sns as sns |
|
|
|
t = Template() |
|
t.add_description("Github Hook -> SNS -> Lambda -> Jenkins REST api") |
|
|
|
### Parameters |
|
params = {} |
|
params["JenkinsUrl"] = t.add_parameter(Parameter( |
|
"JenkinsUrl", |
|
Type="String", |
|
AllowedPattern="[a-zA-Z0-9][a-zA-Z0-9-.]*[a-zA-Z0-9]" |
|
)) |
|
|
|
params["JenkinsProtocol"] = t.add_parameter(Parameter( |
|
"JenkinsProtocol", |
|
Type="String", |
|
Default="HTTP", |
|
AllowedValues=['HTTP','HTTPS'] |
|
)) |
|
|
|
params["JenkinsPort"] = t.add_parameter(Parameter( |
|
"JenkinsPort", |
|
Type="Number", |
|
Default="80", |
|
MinValue=1, |
|
MaxValue=65535 |
|
)) |
|
|
|
params["WatchedBranches"] = t.add_parameter(Parameter( |
|
"WatchedBranches", |
|
Type="CommaDelimitedList", |
|
Default="master, develop, feature, hotfix, release" |
|
)) |
|
# vpc |
|
# subnets |
|
|
|
### Resources |
|
## SNS |
|
topic = t.add_resource(sns.Topic("GithubHookTopic", DisplayName="GithubHook")) |
|
|
|
## IAM |
|
# Github user |
|
githubUser = t.add_resource(iam.User( |
|
"GithubUser", |
|
Policies=[iam.Policy( |
|
PolicyName="GithubUserPolicy", |
|
PolicyDocument={ |
|
"Version": "2012-10-17", |
|
"Statement": [ |
|
{ "Action": [ "sns:Publish" ], |
|
"Resource": [ Ref(topic) ], |
|
"Effect": "Allow" }]})])) |
|
|
|
githubKeys = t.add_resource(iam.AccessKey( |
|
"GithubKeys", |
|
Status="Active", |
|
UserName = Ref(githubUser))) |
|
|
|
# Lambda role |
|
lambdaRole = t.add_resource(iam.Role( |
|
"GithubHookRole", |
|
AssumeRolePolicyDocument={ |
|
"Version": "2012-10-17", |
|
"Statement": [{ |
|
"Action": "sts:AssumeRole", |
|
"Principal": { "Service": "lambda.amazonaws.com" }, |
|
"Effect": "Allow" |
|
}] |
|
}, |
|
# NOTE: this role is a little to permissive, find ways to lock it down |
|
# copied from example execution policy |
|
Policies=[iam.Policy( |
|
PolicyName="GithubHookRolePolicy", |
|
PolicyDocument={ |
|
"Version": "2012-10-17", |
|
"Statement": [ |
|
{ "Effect": "Allow", |
|
"Action": [ |
|
"logs:CreateLogGroup", |
|
"logs:CreateLogStream", |
|
"logs:PutLogEvents" ], |
|
"Resource": "arn:aws:logs:*:*:*" }, |
|
{ "Effect": "Allow", |
|
"Action": [ |
|
"ec2:CreateNetworkInterface", |
|
"ec2:DescribeNetworkInterfaces", |
|
"ec2:DetachNetworkInterface", |
|
"ec2:DeleteNetworkInterface" ], |
|
"Resource": "*" } ] |
|
}) |
|
] |
|
)) |
|
|
|
## Lambda |
|
# load code |
|
# NOTE: line by line is less efficient but easier to validate by eye |
|
# also, this is just a messy parser |
|
f = open("github_hook.js", "r") |
|
lines = [] |
|
ref_re = re.compile("\{\{(ref: [a-zA-Z][a-zA-Z0-9]*)\}\}") |
|
for line in f.readlines(): |
|
# shortcut if no match |
|
if not ref_re.search(line): |
|
lines.append(line) |
|
|
|
else: |
|
parts = [] |
|
for part in ref_re.split(line): |
|
if part.startswith("ref: "): |
|
name = part[5:] |
|
typ = params[name].properties["Type"] |
|
|
|
if typ.startswith("List") or typ == "CommaDelimitedList": |
|
parts.append( Join(",", Ref(name) ) ) |
|
else: |
|
parts.append( Ref(name) ) |
|
|
|
else: |
|
parts.append(part) |
|
lines.append( Join("", parts) ) |
|
|
|
f.close() |
|
code = Join('', lines) |
|
|
|
|
|
# resource |
|
lambdaFn = t.add_resource(awslambda.Function( |
|
"GithubHookLambda", |
|
Description="Consumes Github event information and triggers jenkins builds", |
|
Role=GetAtt(lambdaRole.title, "Arn"), |
|
Runtime="nodejs", |
|
Handler="index.handler", # don't love this is hard coded |
|
MemorySize=128, # in MB |
|
Timeout=10, # in seconds |
|
Code=awslambda.Code(ZipFile=code) |
|
)) |
|
|
|
### Outputs |
|
t.add_output([ |
|
Output("SNSTopic", |
|
Description="ARN for Github", |
|
Value=Ref(topic)), |
|
Output("GithubAccessKey", |
|
Description="Access key for github user", |
|
Value=Ref(githubKeys)), |
|
Output("GithubSecretKey", |
|
Description="Secret key for github user", |
|
Value=GetAtt(githubKeys, "SecretAccessKey")), |
|
Output("Region", |
|
Description="Region to use in github", |
|
Value=Ref(AWS_REGION)), |
|
Output("FinalSteps", Description="final steps to do", Value="1) setup data mapping in lambda, 2) add lambda to VPC if needed") |
|
]) |
|
|
|
print t.to_json() |