Skip to content

Commit

Permalink
Update_061224_5
Browse files Browse the repository at this point in the history
  • Loading branch information
Buckingham authored and Buckingham committed Dec 6, 2024
1 parent f8728eb commit a039acc
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 0 deletions.
7 changes: 7 additions & 0 deletions terraform/environments/ppud/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -1389,4 +1389,11 @@ resource "aws_iam_role_policy_attachment" "lambda_vpc_access_policy_prod" {
count = local.is-production == true ? 1 : 0
role = aws_iam_role.lambda_role_cloudwatch_get_metric_data_prod[0].id
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
}

resource "aws_iam_policy_attachment" "attach_lambda_cloudwatch_full_access_prod" {
count = local.is-production == true ? 1 : 0
name = "lambda-cloudwatch-full-access-iam-attachment"
roles = [aws_iam_role.lambda_role_cloudwatch_get_metric_data_prod[0].id]
policy_arn = "arn:aws:iam::aws:policy/CloudWatchFullAccessV2"
}
52 changes: 52 additions & 0 deletions terraform/environments/ppud/lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -554,3 +554,55 @@ data "archive_file" "zip_the_ppud_email_report_prod" {
source_dir = "${path.module}/lambda_scripts/"
output_path = "${path.module}/lambda_scripts/ppud_email_report_prod.zip"
}

###################################################
# Lambda Function to graph PPUD ELB Requests - PROD
###################################################

resource "aws_lambda_permission" "allow_lambda_to_query_cloudwatch_ppud_elb_report_prod" {
count = local.is-production == true ? 1 : 0
statement_id = "AllowAccesstoCloudWatch"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.terraform_lambda_func_ppud_elb_report_prod[0].function_name
principal = "cloudwatch.amazonaws.com"
source_arn = "arn:aws:cloudwatch:eu-west-2:${local.environment_management.account_ids["ppud-production"]}:*"
}

resource "aws_lambda_function" "terraform_lambda_func_ppud_elb_report_prod" {
# checkov:skip=CKV_AWS_117: "PPUD Lambda functions do not require VPC access and can run in no-VPC mode"
count = local.is-production == true ? 1 : 0
filename = "${path.module}/lambda_scripts/ppud_elb_report_prod.zip"
function_name = "ppud_elb_report"
role = aws_iam_role.lambda_role_cloudwatch_get_metric_data_prod[0].arn
handler = "ppud_elb_report_prod.lambda_handler"
runtime = "python3.12"
timeout = 300
depends_on = [aws_iam_role_policy_attachment.attach_lambda_policy_cloudwatch_get_metric_data_to_lambda_role_cloudwatch_get_metric_data_prod]
reserved_concurrent_executions = 5
# code_signing_config_arn = "arn:aws:lambda:eu-west-2:${local.environment_management.account_ids["ppud-production"]}:code-signing-config:csc-0bafee04a642a41c1"
# dead_letter_config {
# target_arn = aws_sqs_queue.lambda_queue_prod[0].arn
# }
tracing_config {
mode = "Active"
}
layers = [
"arn:aws:lambda:eu-west-2:${data.aws_ssm_parameter.klayers_account_prod[0].value}:layer:Klayers-p312-numpy:8",
"arn:aws:lambda:eu-west-2:${data.aws_ssm_parameter.klayers_account_prod[0].value}:layer:Klayers-p312-pillow:1",
aws_lambda_layer_version.lambda_layer_matplotlib_prod[0].arn
]
# VPC configuration
vpc_config {
subnet_ids = [data.aws_subnet.private_subnets_b.id]
security_group_ids = [aws_security_group.PPUD-Mail-Server[0].id]
}
}

# Archive the zip file

data "archive_file" "zip_the_ppud_elb_report_prod" {
count = local.is-production == true ? 1 : 0
type = "zip"
source_dir = "${path.module}/lambda_scripts/"
output_path = "${path.module}/lambda_scripts/ppud_elb_report_prod.zip"
}
148 changes: 148 additions & 0 deletions terraform/environments/ppud/lambda_scripts/ppud_elb_report_prod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import boto3
import os
os.environ['MPLCONFIGDIR'] = "/tmp/graph"
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from botocore.exceptions import NoCredentialsError, PartialCredentialsError
import base64
import smtplib

# Configuration
CURRENT_DATE = datetime.now().strftime('%a %d %b %Y')
SENDER = '[email protected]'
RECIPIENTS = ['[email protected]']
SUBJECT = f'AWS Daily PPUD ELB Request Report - {CURRENT_DATE}'
AWS_REGION = 'eu-west-2'
ELB_NAME = "PPUD-ALB" # Replace with your ELB name

# SMTP Configuration
SMTP_SERVER = "10.27.9.39"
SMTP_PORT = 25

# Initialize AWS clients
cloudwatch = boto3.client("cloudwatch", region_name=AWS_REGION)
ses = boto3.client("ses", region_name=AWS_REGION)

def get_hourly_request_counts(elb_name):
"""Fetches daily connection counts for the ELB from CloudWatch."""
end_time = datetime.utcnow()
start_time = end_time - timedelta(days=1) # Fetch data for the last 1 day

response = cloudwatch.get_metric_statistics(
Namespace="AWS/ELB",
MetricName="RequestCount",
Dimensions=[
{"Name": "LoadBalancerName", "Value": elb_name}
],
StartTime=start_time,
EndTime=end_time,
Period=3600, # Daily period
Statistics=["Sum"]
)

data_points = sorted(response["Datapoints"], key=lambda x: x["Timestamp"])
return [(dp["Timestamp"].strftime('%H:%M'), dp["Sum"]) for dp in data_points]

def plot_graph(request_data):
"""Plots the graph of hourly requests and returns it as an in-memory file."""
times, requests = zip(*request_data)
plt.figure(figsize=(20, 6))
plt.bar(times, requests, color="blue")
plt.title(f"Hourly Requests to {ELB_NAME} Over the Last 24 Hours")
plt.xlabel("Time (UTC)")
plt.ylabel("Number of Requests")
plt.xticks(rotation=45)
plt.grid(axis="y", linestyle="--", linewidth=0.7, alpha=0.7)
plt.tight_layout()

# graph_path = "elb_daily_connections.png"
# plt.savefig(graph_path)
# plt.close()
# return graph_path

# Save the graph to a temporary buffer
temp_file = "/tmp/elb_daily_connections.png"
plt.savefig(temp_file)
plt.close()

# Read the image and encode it to base64
with open(temp_file, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode("utf-8")

# Cleanup temporary file
os.remove(temp_file)
return encoded_string

# Function to send an email via SES
def send_email_with_graph(graph_base64):
"""
Send an email with the graph embedded in the email body using AWS SES.
"""
cloudwatch = boto3.client("cloudwatch", region_name=AWS_REGION)

# Email body with the embedded image
email_body = f"""
<html>
<body>
<p>Hi Team,</p>
<p>Please find below the daily PPUD ELB Request Report.</p>
<img src="data:image/png;base64,{graph_base64}" alt="PPUD ELB Request Report" />
<p>This is an automated email.</p>
</body>
</html>
"""

# Create the email message
msg = MIMEMultipart("alternative")
msg["From"] = SENDER
msg["To"] = ", ".join(RECIPIENTS)
msg["Subject"] = SUBJECT

# Attach the HTML body
msg.attach(MIMEText(email_body, "html"))

# Send the email with AWS SES
# try:
# response = ses_client.send_raw_email(
# Source=SENDER,
# Destinations=RECIPIENTS,
# RawMessage={"Data": msg.as_string()},
# )
# print("Email sent! Message ID:", response["MessageId"])
# except Exception as e:
# print("Error sending email:", e)
# raise

# Send the email with an EC2 Instance Mail Relay
try:
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
# server.starttls()
# server.login(SENDER, EMAIL_PASSWORD)
server.sendmail(SENDER, RECIPIENTS, msg.as_string())
print("Email sent successfully.")
except Exception as e:
print(f"Error sending email: {e}")

def lambda_handler(event, context):
try:
# Get hourly request counts
request_data = get_hourly_request_counts(ELB_NAME)
if not request_data:
print("No data found for the specified ELB.")
return

# Create graph
temp_file = plot_graph(request_data)

# Send email
send_email_with_graph(SENDER, temp_file)
print("Process completed successfully.")

except (NoCredentialsError, PartialCredentialsError) as cred_error:
print(f"Credential issue: {cred_error}")
except Exception as e:
print(f"An error occurred: {e}")

0 comments on commit a039acc

Please sign in to comment.