Skip to content

Commit

Permalink
Merge pull request #16 from RavenEsc/security-secrets
Browse files Browse the repository at this point in the history
Security secrets
  • Loading branch information
RavenEsc authored Jan 8, 2025
2 parents 34937cc + 993ce41 commit a690c36
Show file tree
Hide file tree
Showing 9 changed files with 660 additions and 617 deletions.
10 changes: 7 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
config/
.devcontainer
.vscode
#.vscode
config/
.devcontainer
.vscode
#tf
.terraform
.terraform.lock.hcl
54 changes: 39 additions & 15 deletions code/discordlambda/discordnote.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,38 @@
import json
from discord_webhook import DiscordWebhook, DiscordEmbed
import traceback
import boto3

# Initialize logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
try:
# Pulls from SQS event trigger, checks each result in the list, sets each necessary value within the elements read
records = event['Records']
for record in records:
message = json.loads(record['body'])
for item in message:
# Alert Value so far between 'EC2_Public_Instance',
# Alert Value so far between 'EC2_Public_Instance', 'IAM Group Admin', 'IAM Admin User', & 'IAM Admin Role'
alert = item['Alert']
try:
# Grabs Secret from AWS Secrets Manager and sets it as a variable
secret_name = "tfc/sat/discordwebhook"
region_name = "us-east-1"

# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(
service_name='secretsmanager',
region_name=region_name
)
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)

secret = get_secret_value_response['SecretString']
webhook = DiscordWebhook(url=secret)
# EC2 Public Instance
if alert == 'EC2_Public_Instance':
# EC2 values set as variables
Expand All @@ -26,11 +46,10 @@ def lambda_handler(event, context):

try:
# Sends the PublicEC2 Alert message formatted to be easily readable to Discord channel webhook integration, pings all users who can see the channel
webhook = DiscordWebhook(url="https://discordapp.com/api/webhooks/1147701063630196786/PVU9g477tn2u9ko0LZ5uTg4SUoQGqe_iSftGdhjZi1Szz5aIDDEew4soEPL80S3EYizy")
embed = DiscordEmbed(
title="Public EC2 Instance!",
description=f"Instance ID: {id}\nPublic IP: {public_ip}\nAttachment Time: {time_created}\nOpen Ports: {open_ports}\n\n@everyone",
allowed_mentions={"everyone"},
description=f"Instance ID: {id}\nPublic IP: {public_ip}\nAttachment Time: {time_created}\nOpen Ports: {open_ports}\n\n@ravnsymphony",
allowed_mentions={"ravnsymphony"},
color=0x03b2f8
)
webhook.add_embed(embed)
Expand All @@ -44,8 +63,7 @@ def lambda_handler(event, context):
return {
"statusCode": 500,
"body": {"message": f"Error sending Discord message: {e}"}
}

}
# IAM Group Admin
elif alert == 'Unauthorized_Admin_Group':
# IAM values set as variables
Expand All @@ -54,11 +72,10 @@ def lambda_handler(event, context):

try:
# Sends the PublicEC2 Alert message formatted to be easily readable to Discord channel webhook integration, pings all users who can see the channel
webhook = DiscordWebhook(url="https://discordapp.com/api/webhooks/1147701063630196786/PVU9g477tn2u9ko0LZ5uTg4SUoQGqe_iSftGdhjZi1Szz5aIDDEew4soEPL80S3EYizy")
embed = DiscordEmbed(
title="Unauthorized Admin!",
description=f"Group Name: {group}\nID: {group_id}\n\n@everyone",
allowed_mentions={"everyone"},
description=f"Group Name: {group}\nID: {group_id}\n\n@ravnsymphony",
allowed_mentions={"ravnsymphony"},
color=0x03b2f8
)
webhook.add_embed(embed)
Expand All @@ -81,11 +98,10 @@ def lambda_handler(event, context):

try:
# Sends the PublicEC2 Alert message formatted to be easily readable to Discord channel webhook integration, pings all users who can see the channel
webhook = DiscordWebhook(url="https://discordapp.com/api/webhooks/1147701063630196786/PVU9g477tn2u9ko0LZ5uTg4SUoQGqe_iSftGdhjZi1Szz5aIDDEew4soEPL80S3EYizy")
embed = DiscordEmbed(
title="Unauthorized Admin!",
description=f"User Name: {user}\nID: {user_id}\n\n@everyone",
allowed_mentions={"everyone"},
description=f"User Name: {user}\nID: {user_id}\n\n@ravnsymphony",
allowed_mentions={"ravnsymphony"},
color=0x03b2f8
)
webhook.add_embed(embed)
Expand All @@ -108,11 +124,10 @@ def lambda_handler(event, context):

try:
# Sends the PublicEC2 Alert message formatted to be easily readable to Discord channel webhook integration, pings all users who can see the channel
webhook = DiscordWebhook(url="https://discordapp.com/api/webhooks/1147701063630196786/PVU9g477tn2u9ko0LZ5uTg4SUoQGqe_iSftGdhjZi1Szz5aIDDEew4soEPL80S3EYizy")
embed = DiscordEmbed(
title="Unauthorized Admin!",
description=f"Role Name: {role}\nID: {role_id}\n\n@everyone",
allowed_mentions={"everyone"},
description=f"Role Name: {role}\nID: {role_id}\n\n@ravnsymphony",
allowed_mentions={"ravnsymphony"},
color=0x03b2f8
)
webhook.add_embed(embed)
Expand All @@ -127,6 +142,15 @@ def lambda_handler(event, context):
"statusCode": 500,
"body": {"message": f"Error sending Discord message: {e}"}
}
except Exception as e:
traceback_message = traceback.format_exc()
logger.error(f"Error grabbing from Secret Manager: {e}")
logger.error(traceback_message)
logger.error(message)
return {
"statusCode": 500,
"body": {"message": f"Error grabbing from Secret Manager: {e}"}
}
# Handles the errors for recieving the messages to Discord
except Exception as e:
traceback_message = traceback.format_exc()
Expand Down
222 changes: 111 additions & 111 deletions code/iamadminchecklambda/opiam-check.py
Original file line number Diff line number Diff line change
@@ -1,111 +1,111 @@
import logging
import os
import json
import boto3
import traceback

# Initialize logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
try:
policy_arn = 'arn:aws:iam::aws:policy/AdministratorAccess'

# Get the list of all users attached to the policy
iam = boto3.client('iam')
policies = iam.list_entities_for_policy(PolicyArn=policy_arn)

# Read the authorized IDs from the configuration file
with open('authorized_ids.json') as f:
authorized_ids = json.load(f)

# Extract the authorized IDs for groups, users, and roles
id_authorized_groups = authorized_ids['AuthorizedGroups']
id_authorized_users = authorized_ids['AuthorizedUsers']
id_authorized_roles = authorized_ids['AuthorizedRoles']

# Check if the policy is used where it shouldn't be
Unauthorized_Admins = []

for group in policies['PolicyGroups']:
group_id = group['GroupId']
if group_id not in id_authorized_groups:
Unauthorized_Admins.append(group)

for user in policies['PolicyUsers']:
user_id = user['UserId']
if user_id not in id_authorized_users:
Unauthorized_Admins.append(user)

for role in policies['PolicyRoles']:
Role_id = role['RoleId']
if Role_id not in id_authorized_roles:
Unauthorized_Admins.append(role)

# Handles the errors for reading the IAM entities by policy
except Exception as e:
traceback_msg = traceback.format_exc()
logging.error(f"Error reading/listing IAM Entities: {str(e)}")
logging.error(traceback_msg)
return {
'statusCode': 500,
'body': {"message": f"Error reading/listing IAM Entities: {str(e)}"}
}

# Check if the Unauthorized_Admins list is empty
if not Unauthorized_Admins:
# Return a status code 200 with a body 'No Results to publish'
return {'statusCode': 200, 'body': 'No Results to publish'}
else:
# Filter to only UserName and UserID
filtered_UnAuth = []
for Unauthorized_Admin in Unauthorized_Admins:
if 'GroupName' in Unauthorized_Admin:
Group = {
"Alert": "Unauthorized_Admin_Group",
"Group": Unauthorized_Admin['GroupName'],
"ID": Unauthorized_Admin['GroupId'],
}
filtered_UnAuth.append(Group)

elif 'UserName' in Unauthorized_Admin:
User = {
"Alert": "Unauthorized_Admin_User",
"User": Unauthorized_Admin['UserName'],
"ID": Unauthorized_Admin['UserId'],
}
filtered_UnAuth.append(User)

elif 'RoleName' in Unauthorized_Admin:
Role = {
"Alert": "Unauthorized_Admin_Role",
"Role": Unauthorized_Admin['RoleName'],
"ID": Unauthorized_Admin['RoleId'],
}
filtered_UnAuth.append(Role)


# Publish the results to the SNS topic
sns = boto3.client('sns')
try:
pub_message=json.dumps(filtered_UnAuth, default=str, indent=4)
sns.publish(
TopicArn=os.getenv('SNS_TOPIC_ARN'),
Message=pub_message,
Subject='List of Unauthorized_Admins'
)

# Return a status code 200 with a body 'Results published to SNS'
return {'statusCode': 200, 'body': 'Results published to SNS'}

# Handles the errors for pushing the results to the SNS topic
except Exception as e:
traceback_msg = traceback.format_exc()
logging.error(f"Error publishing to SNS Topic: {str(e)}")
logging.error(traceback_msg)
logging.error(pub_message)
return {
'statusCode': 500,
'body': {"message": f"Error publishing to SNS Topic: {str(e)}"}
}
import logging
import os
import json
import boto3
import traceback

# Initialize logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
try:
policy_arn = 'arn:aws:iam::aws:policy/AdministratorAccess'

# Get the list of all users attached to the policy
iam = boto3.client('iam')
policies = iam.list_entities_for_policy(PolicyArn=policy_arn)

# Read the authorized IDs from the configuration file
with open('authorized_ids.json') as f:
authorized_ids = json.load(f)

# Extract the authorized IDs for groups, users, and roles
id_authorized_groups = authorized_ids['AuthorizedGroups']
id_authorized_users = authorized_ids['AuthorizedUsers']
id_authorized_roles = authorized_ids['AuthorizedRoles']

# Check if the policy is used where it shouldn't be
Unauthorized_Admins = []

for group in policies['PolicyGroups']:
group_id = group['GroupId']
if group_id not in id_authorized_groups:
Unauthorized_Admins.append(group)

for user in policies['PolicyUsers']:
user_id = user['UserId']
if user_id not in id_authorized_users:
Unauthorized_Admins.append(user)

for role in policies['PolicyRoles']:
Role_id = role['RoleId']
if Role_id not in id_authorized_roles:
Unauthorized_Admins.append(role)

# Handles the errors for reading the IAM entities by policy
except Exception as e:
traceback_msg = traceback.format_exc()
logging.error(f"Error reading/listing IAM Entities: {str(e)}")
logging.error(traceback_msg)
return {
'statusCode': 500,
'body': {"message": f"Error reading/listing IAM Entities: {str(e)}"}
}

# Check if the Unauthorized_Admins list is empty
if not Unauthorized_Admins:
# Return a status code 200 with a body 'No Results to publish'
return {'statusCode': 200, 'body': 'No Results to publish'}
else:
# Filter to only UserName and UserID
filtered_UnAuth = []
for Unauthorized_Admin in Unauthorized_Admins:
if 'GroupName' in Unauthorized_Admin:
Group = {
"Alert": "Unauthorized_Admin_Group",
"Group": Unauthorized_Admin['GroupName'],
"ID": Unauthorized_Admin['GroupId'],
}
filtered_UnAuth.append(Group)

elif 'UserName' in Unauthorized_Admin:
User = {
"Alert": "Unauthorized_Admin_User",
"User": Unauthorized_Admin['UserName'],
"ID": Unauthorized_Admin['UserId'],
}
filtered_UnAuth.append(User)

elif 'RoleName' in Unauthorized_Admin:
Role = {
"Alert": "Unauthorized_Admin_Role",
"Role": Unauthorized_Admin['RoleName'],
"ID": Unauthorized_Admin['RoleId'],
}
filtered_UnAuth.append(Role)


# Publish the results to the SNS topic
sns = boto3.client('sns')
try:
pub_message=json.dumps(filtered_UnAuth, default=str, indent=4)
sns.publish(
TopicArn=os.getenv('SNS_TOPIC_ARN'),
Message=pub_message,
Subject='List of Unauthorized_Admins'
)

# Return a status code 200 with a body 'Results published to SNS'
return {'statusCode': 200, 'body': 'Results published to SNS'}

# Handles the errors for pushing the results to the SNS topic
except Exception as e:
traceback_msg = traceback.format_exc()
logging.error(f"Error publishing to SNS Topic: {str(e)}")
logging.error(traceback_msg)
logging.error(pub_message)
return {
'statusCode': 500,
'body': {"message": f"Error publishing to SNS Topic: {str(e)}"}
}
Loading

0 comments on commit a690c36

Please sign in to comment.