Skip to content

Commit

Permalink
added reminders + refactor
Browse files Browse the repository at this point in the history
Signed-off-by: Trey <[email protected]>
  • Loading branch information
TreyWW committed Jul 22, 2024
1 parent d7ac271 commit f17d37b
Show file tree
Hide file tree
Showing 16 changed files with 531 additions and 115 deletions.
180 changes: 171 additions & 9 deletions .github/management_bot/pulumi/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import json
import pulumi

from pulumi_aws import apigateway, iam
from pulumi_aws import apigateway, iam, scheduler
from pulumi_aws import lambda_

config = pulumi.Config()
Expand All @@ -13,9 +13,15 @@
region = config.get("region", "eu-west-2")
tags = {"app": site_name}

# Reminders

reminders_group = scheduler.ScheduleGroup("invoice_reminders_group", name=f"myfinances-github-bot-remind_me")

# lambda_layer
lambda_access_role = iam.Role(
"lambda_access_role",
name="lambda_role",
path="/myfinances/management_bot/",
assume_role_policy=json.dumps(
{
"Version": "2012-10-17",
Expand All @@ -33,23 +39,176 @@
),
)

# <editor-fold desc="lambda_execution_policy">
# This goes on Lambda to send comment
lambda_execution_policy = iam.Policy(
"lambda-execution-policy",
name=f"lambda-execution-policy",
path="/myfinances/management_bot/",
policy=json.dumps(
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CreateLogDelivery",
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"ssm:GetParametersByPath",
"ssm:GetParameters",
"ssm:GetParameter",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
],
"Resource": [
"arn:aws:ssm:*:*:parameter/myfinances/github_bot/*",
"arn:aws:kms:*:*:key/*",
"arn:aws:logs:*:*:log-group:/aws/lambda/myfinances_github_bot_webhooks:*",
"arn:aws:logs:*:*:log-group:/aws/lambda/myfinances_github_bot_reminders:*",
"arn:aws:logs:*:*:log-group:/aws/lambda/myfinances_github_bot_webhooks:*:log-stream:*",
"arn:aws:logs:*:*:log-group:/aws/lambda/myfinances_github_bot_reminders:*:log-stream:*",
],
}
],
}
),
)
# </editor-fold>

# <editor-fold desc="lambda_execution_policy_attachment">
lambda_execution_policy_attachment = iam.RolePolicyAttachment(
"lambda-execution-policy-attach",
policy_arn=lambda_execution_policy.arn,
role=lambda_access_role.name,
opts=pulumi.ResourceOptions(depends_on=[lambda_access_role, lambda_execution_policy]),
)
# </editor-fold>

# <editor-fold desc="scheduler_execution_policy">

scheduler_execution_policy = iam.Policy(
"scheduler-execution-policy",
name=f"reminder-scheduler-execution-policy",
path="/myfinances/management_bot/",
policy=json.dumps(
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeLambda",
"Effect": "Allow",
"Action": ["lambda:InvokeFunction"],
"Resource": "arn:aws:lambda:*:*:function:myfinances_github_bot_reminders",
},
{
"Sid": "AllowEventbridgeScheduler",
"Effect": "Allow",
"Action": ["scheduler:*"],
"Resource": "*",
},
],
}
),
)
# </editor-fold>

# <editor-fold desc="scheduler_execution_role">
scheduler_execution_role = iam.Role(
"scheduler-execution-role",
name="reminder-scheduler-execution-role",
path="/myfinances/management_bot/",
assume_role_policy=json.dumps(
{
"Version": "2012-10-17",
"Statement": [{"Effect": "Allow", "Principal": {"Service": "scheduler.amazonaws.com"}, "Action": "sts:AssumeRole"}],
}
),
)
# </editor-fold>

# <editor-fold desc="scheduler_execution_policy_attachment">
scheduler_execution_policy_attachment = iam.RolePolicyAttachment(
"scheduler-execution-policy-attach",
policy_arn=scheduler_execution_policy.arn,
role=scheduler_execution_role.name,
opts=pulumi.ResourceOptions(depends_on=[scheduler_execution_policy, scheduler_execution_role]),
)
# </editor-fold>

scheduler_user = iam.User("scheduler_user", name="myfinances-github-bot-scheduler")

reminders_create_schedule_policy = iam.Policy(
"reminders_create_schedule_policy",
name="myfinances-github-bot-reminders-create-schedule-policy",
path="/myfinances/management_bot/",
policy=json.dumps(
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEventbridgeScheduler",
"Effect": "Allow",
"Action": ["scheduler:CreateSchedule"],
"Resource": "arn:aws:scheduler:*:*:schedule/myfinances-github-bot-remind_me/*",
},
{
"Sid": "AllowRolePass",
"Effect": "Allow",
"Action": ["iam:PassRole"],
"Resource": "arn:aws:iam::*:role/myfinances/management_bot/reminder-scheduler-execution-role",
},
],
}
),
)

iam.UserPolicyAttachment(
"scheduler_user_policy_attachment",
policy_arn=reminders_create_schedule_policy.arn,
user=scheduler_user.name,
opts=pulumi.ResourceOptions(depends_on=[reminders_create_schedule_policy, scheduler_user]),
)

scheduler_access_role_key = iam.AccessKey(
"lambda_access_role_key", user=scheduler_user.name, opts=pulumi.ResourceOptions(depends_on=[scheduler_user])
)

lambda_layer = lambda_.LayerVersion(
"lambda_layer", code=pulumi.FileArchive(config.require("lambda_zip_path")), layer_name="PyGithub_for_myfinances_management_bot"
)

# lambda_ssm_layer = lambda_.LayerVersion(
# "lambda_ssm_layer", layer_name="AWS-Parameters-and-Secrets-Lambda-Extension",
# )
reminder_handler_lambda_func = lambda_.Function(
"reminder_lambda",
name="myfinances_github_bot_reminders",
role=lambda_access_role.arn,
code=pulumi.AssetArchive({".": pulumi.FileArchive("./reminder_handler")}),
handler="lambda_handler.lambda_handler",
timeout=8,
runtime=lambda_.Runtime.PYTHON3D12,
environment=lambda_.FunctionEnvironmentArgs(variables={"ssm_prefix": "/myfinances/github_bot/"}),
layers=[lambda_layer.arn, "arn:aws:lambda:eu-west-2:133256977650:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11"],
tags={"project": "MyFinancesBot"},
)

lambda_func = lambda_.Function(
main_lambda_func = lambda_.Function(
"webhook_lambda",
name="myfinances_github_bot_webhooks",
role=lambda_access_role.arn,
code=pulumi.AssetArchive({".": pulumi.FileArchive("./src")}),
code=pulumi.AssetArchive({".": pulumi.FileArchive("./webhook_handler")}),
handler="lambda_handler.lambda_handler",
timeout=8,
runtime=lambda_.Runtime.PYTHON3D12,
environment=lambda_.FunctionEnvironmentArgs(variables={"ssm_prefix": "/myfinances/github_bot/"}),
environment=lambda_.FunctionEnvironmentArgs(
variables={
"ssm_prefix": "/myfinances/github_bot/",
"AWS_REMINDER_LAMBDA_ARN": reminder_handler_lambda_func.arn,
"AWS_REMINDER_LAMBDA_ROLE_ARN": scheduler_execution_role.arn,
"AWS_SCHEDULES_ACCESS_KEY_ID": scheduler_access_role_key.id,
"AWS_SCHEDULES_SECRET_ACCESS_KEY": scheduler_access_role_key.secret,
"AWS_SCHEDULES_REGION_NAME": region,
}
),
layers=[lambda_layer.arn, "arn:aws:lambda:eu-west-2:133256977650:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11"],
tags={"project": "MyFinancesBot"},
)
Expand Down Expand Up @@ -82,7 +241,8 @@
integration_http_method="POST",
type="AWS",
timeout_milliseconds=8000,
uri=lambda_func.invoke_arn,
content_handling="CONVERT_TO_TEXT",
uri=main_lambda_func.arn.apply(lambda arn: arn + ":${stageVariables.lambda_function_version}"), # main_lambda_func.invoke_arn,
)

api_gw_200_resp = apigateway.MethodResponse(
Expand All @@ -107,7 +267,7 @@
"apigw_lambda",
statement_id="AllowExecutionFromAPIGateway",
action="lambda:InvokeFunction",
function=lambda_func.name,
function=main_lambda_func.name,
principal="apigateway.amazonaws.com",
source_arn=pulumi.Output.all(rest_api.id).apply(lambda id: f"arn:aws:execute-api:{region}:{account_id}:{id[0]}/*/POST/"),
)
Expand All @@ -123,3 +283,5 @@
)

pulumi.export("invoke_url", prod_stage.invoke_url)
pulumi.export("scheduler_execution_role", scheduler_execution_role.arn)
pulumi.export("reminder_handler_lambda_func", reminder_handler_lambda_func.arn)
63 changes: 63 additions & 0 deletions .github/management_bot/pulumi/reminder_handler/lambda_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import json
import os, base64
import urllib.request
from textwrap import dedent

from github import Github, Issue, GithubIntegration, PullRequest
from github import Auth

import logging
import helpers

logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG if os.environ.get("DEBUG") else logging.DEBUG) # todo go back to info
logger = logging.getLogger(__name__)

aws_session_token = os.environ.get("AWS_SESSION_TOKEN")

REPOSITORY_NAME = "TreyWW/MyFinances"


def lambda_handler(event: dict, lambda_context):
print(f"EVENT_DETAILS: {event}")
# https://docs.aws.amazon.com/systems-manager/latest/userguide/ps-integration-lambda-extensions.html
stage = "production"
req = urllib.request.Request(
f"http://localhost:2773/systemsmanager/parameters/get?withDecryption=true&name=%2Fmyfinances%2Fgithub_bot%2F{stage}"
)
req.add_header("X-Aws-Parameters-Secrets-Token", aws_session_token)
config = urllib.request.urlopen(req).read()

ssm_result: json = json.loads(config)
ssm_value: json = json.loads(ssm_result["Parameter"]["Value"])

PRIVATE_KEY = helpers.decode_private_key(ssm_value["private_key"])
APP_ID = ssm_value["app_id"]

auth = Auth.AppAuth(APP_ID, PRIVATE_KEY)
gi = GithubIntegration(auth=auth)
g: Github = gi.get_installations()[0].get_github_for_installation()

repository = g.get_repo(REPOSITORY_NAME)

target: Issue.Issue | PullRequest.PullRequest
message: str = event.get("message")

if issue_id := event.get("issue_id"):
target = repository.get_issue(issue_id)
elif pr_id := event.get("pr_id"):
target = repository.get_pull(pr_id)
else:
raise ValueError("No issue or pull request specified")

target.create_comment(
dedent(
f"""
:wave: @{event.get("user")}, {message if message else "you set a reminder for now!"}
{helpers.del_reply_comment()}
"""
)
)

return {"statusCode": 200, "body": json.dumps({}), "headers": {"Content-Type": "application/json"}}
Loading

0 comments on commit f17d37b

Please sign in to comment.