Skip to content

Commit

Permalink
Feat/sec alarms (#978)
Browse files Browse the repository at this point in the history
* add(module): new module

* chore(modules): split into multiple modules

* fix(bug): missing chars

* fix(bugs): missing policies

* chore(documentation): for changes and additions

* fix(bugs): and a few additions

* rem(prints): leftovers from debugging

* chore(lambda): code optimization

* add(test): lambda function test through pytest

* add(automation): for implemetation in masses or remotely

* fix(bug): functions not properly called
  • Loading branch information
fauzigo committed Sep 16, 2019
1 parent 9766e10 commit c245c6b
Show file tree
Hide file tree
Showing 21 changed files with 655 additions and 7 deletions.
1 change: 1 addition & 0 deletions Jenkinsfile
Expand Up @@ -26,6 +26,7 @@ node {
sh 'python -m pytest cloud-automation/apis_configs/'
sh 'python -m pytest cloud-automation/gen3/lib/dcf/'
sh 'cd cloud-automation/tf_files/aws/modules/common-logging && python3 -m pytest testLambda.py'
sh 'cd cloud-automation/files/lambda && python3 -m pytest test-security_alerts.py'
sh 'cd cloud-automation/kube/services/jupyterhub && python3 -m pytest test-jupyterhub_config.py'
sh 'bash cloud-automation/files/scripts/es-secgroup-sync.sh test'
}
Expand Down
30 changes: 30 additions & 0 deletions files/lambda/security_alerts.py
@@ -0,0 +1,30 @@

import json
import boto3
import sys
import os

#print('Loading function')
""" Function to define Lambda Handler """

def lambda_handler(event, context):
#print(event)
try:
if event['detail']['eventName'] == 'StopLogging':
if 'topic' in os.environ:
client = boto3.client('cloudtrail')
response = client.start_logging(Name=event['detail']['requestParameters']['name'])
client = boto3.client('sns')
response = client.publish(
TopicArn=os.environ['topic'],
Message=json.dumps({'default': json.dumps(event['detail'])}),
MessageStructure='json'
)
else:
print("lambda test loads")
return event['detail']['eventName']
else:
print(event['detail']['eventName'])
except Exception as e:
print(e)
#sys.exit();
9 changes: 9 additions & 0 deletions files/lambda/test-security_alerts.py
@@ -0,0 +1,9 @@
#!/usr/bin/env python3
import pytest
import security_alerts

example = {'version': '0', 'id': '06ca5e7a-3b6c-0a85-0dc1-c963d8bd31f4', 'detail-type': 'AWS API Call via CloudTrail', 'source': 'aws.cloudtrail', 'account': '707767160287', 'time': '2019-09-12T19:33:22Z', 'region': 'us-east-1', 'resources': [], 'detail': {'eventVersion': '1.05', 'userIdentity': {'type': 'AssumedRole', 'principalId': 'AROAICHVNMYIWEFXZIRDW:fauzi-csoc', 'arn': 'arn:aws:sts::707767160287:assumed-role/csoc_adminvm/fauzi-csoc', 'accountId': '707767160287', 'accessKeyId': 'ASIA2JSRVZXPWWDZ6A5N', 'sessionContext': {'sessionIssuer': {'type': 'Role', 'principalId': 'AROAICHVNMYIWEFXZIRDW', 'arn': 'arn:aws:iam::707767160287:role/csoc_adminvm', 'accountId': '707767160287', 'userName': 'csoc_adminvm'}, 'webIdFederationData': {}, 'attributes': {'mfaAuthenticated': 'true', 'creationDate': '2019-09-12T19:31:40Z'}}}, 'eventTime': '2019-09-12T19:33:22Z', 'eventSource': 'cloudtrail.amazonaws.com', 'eventName': 'StopLogging', 'awsRegion': 'us-east-1', 'sourceIPAddress': '128.135.61.125', 'userAgent': 'console.amazonaws.com', 'requestParameters': {'name': 'arn:aws:cloudtrail:us-east-1:707767160287:trail/cdistest_management_trail'}, 'responseElements': None, 'requestID': '8e0bdee5-8626-4ad4-b5cf-29bada7bef17', 'eventID': '0da7164e-a62d-4bda-811c-4facfbc55df4', 'readOnly': False, 'eventType': 'AwsApiCall'}}

def test_answer():
assert security_alerts.lambda_handler(example,'')

51 changes: 49 additions & 2 deletions gen3/bin/gitops.sh
Expand Up @@ -120,6 +120,9 @@ gen3_run_tfplan() {
"eks")
message=$(_gen3_run_tfplan_eks ${apply})
;;
"management-logs")
message=$(_gen3_run_tfplan_management-logs ${apply})
;;
esac
else
message=$(mktemp -p "$XDG_RUNTIME_DIR" "tmp_plan.XXXXXX")
Expand Down Expand Up @@ -158,6 +161,13 @@ _gen3_run_tfapply_vpc() {
gen3_run_tfplan "$@" "quiet" "apply"
}

#
# Apply changes picket up by tfplan
#
_gen3_run_tfapply_management-logs() {
gen3_run_tfplan "$@" "quiet" "apply"
}

#
# Public function to start tfapply, only for eks, for the VPC it might not be a good idea
# or at least it needs some deeper supervisiohn
Expand All @@ -171,11 +181,14 @@ gen3_run_tfapply() {
elif [ ${module} == "eks" ];
then
_gen3_run_tfapply_eks "$@"
elif [ ${module} == "management-logs" ];
then
_gen3_run_tfapply_management-logs "$@"
fi
}

#
# Function that checks for uncomitter changes to cloud-automation
# Function that checks for uncomitted changes to cloud-automation
# and also if there are unapplied changes to the vpc module
#
_gen3_run_tfplan_vpc() {
Expand Down Expand Up @@ -210,7 +223,7 @@ _gen3_run_tfplan_vpc() {
}

#
# Function that checks for uncomitter changes to cloud-automation
# Function that checks for uncomitted changes to cloud-automation
# and also if there are unapplied changes to the eks module
#
_gen3_run_tfplan_eks() {
Expand Down Expand Up @@ -243,6 +256,40 @@ _gen3_run_tfplan_eks() {
echo "${tempFile}"
}

#
# Function that checks for uncomitted changes to cloud-automation
# and also if there are unapplied changes to the eks module
#
_gen3_run_tfplan_management-logs() {

local plan
local slack_hook
local tempFile
local apply
local output

apply=$1

gen3 workon $(grep profile ~/.aws/config |awk '{print $2}'| cut -d] -f1|head -n1) $(grep profile ~/.aws/config |awk '{print $2}'| cut -d] -f1|head -n1)_management-logs > /dev/null 2>&1
output="$(gen3 tfplan)"
plan=$(echo -e "${output}" | grep "Plan")

if [ -n "${plan}" ];
then
tempFile=$(mktemp -p "$XDG_RUNTIME_DIR" "tmp_plan.XXXXXX")
echo "${vpc_name}_management-logs has unapplied plan:" > ${tempFile}
echo -e "${plan}"| sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" >> ${tempFile}
if [ -n "$apply" -a "$apply" == "apply" ];
then
echo -e "${output}" >> ${tempFile}
gen3 tfapply >> ${tempFile} 2>&1
else
echo "No apply this time" >> ${tempFile}
fi
fi
echo "${tempFile}"
}

# command to update dictionary URL and image versions
#
gen3_gitops_sync() {
Expand Down
3 changes: 3 additions & 0 deletions tf_files/aws/modules/account-management-logs/README.md
Expand Up @@ -2,6 +2,9 @@

Create a cloudtrail to send management logs onto S3 and Cloudwatch for an specific account. Also hook the CloudWatchLogGroup created to the CSOC account through a Subscription filter.

2019-09-11
This module would also deploy a set of security alarms based on Cloudwatch Alerts.

## 1. QuickStart

```
Expand Down
10 changes: 5 additions & 5 deletions tf_files/aws/modules/account-management-logs/cloud.tf
@@ -1,10 +1,10 @@
# We need a bucket for cloud-trail to send logs

module "metrics-alerts" {
source = "../account-management-metrics"
cwl_group = "${aws_cloudwatch_log_group.management-logs_group.name}"
alarm_actions = "${var.alarm_actions}"
}
#module "metrics-alerts" {
# source = "../account-management-metrics"
# cwl_group = "${aws_cloudwatch_log_group.management-logs_group.name}"
# alarm_actions = "${var.alarm_actions}"
#}



Expand Down
126 changes: 126 additions & 0 deletions tf_files/aws/modules/account-management-logs/event-alerts.tf
@@ -0,0 +1,126 @@


module "cloudwatch-events" {
source = "../cloudwatch-events/"
cwe_rule_name = "${var.account_name}-cloudtrail-StopLogging"
cwe_rule_description = "Lets check if someone dares to stop logging"
cwe_target_arn = "${module.alerting-lambda.function_arn}"
cwe_rule_pattern = <<EOP
{
"source": [
"aws.cloudtrail"
],
"detail": {
"eventName": [
"StopLogging"
]
}
}
EOP
# depends_on = ["module.alerting-lambda"]
}

module "alerting-lambda" {
source = "../lambda-function/"
lambda_function_file = "${path.module}/../../../../files/lambda/security_alerts.py"
lambda_function_name = "${var.account_name}-security-alert-lambda"
lambda_function_description = "Checking for things that should or might not happend"
lambda_function_iam_role_arn = "${module.role-for-lambda.role_arn}"
lambda_function_env = {"topic"="arn:aws:sns:us-east-1:433568766270:planx-csoc-alerts-for-bsd-security"}
lambda_function_handler = "security_alerts.lambda_handler"
}

module "role-for-lambda" {
source = "../iam-role/"
role_name = "${var.account_name}-security-alert-role"
role_description = "Role for the alerting lambda function"
role_assume_role_policy = <<EOP
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOP
}

data "aws_iam_policy_document" "sns_access" {
statement {
actions = [
"SNS:Publish",
"SNS:GetTopicAttributes",
]
effect = "Allow"
#resources = ["arn:aws:sns:us-east-1:433568766270:planx-csoc-alerts-for-bsd-securitys"]
resources = ["*"]
}
}


data "aws_iam_policy_document" "cloudtrail_access" {

statement {
actions = [
"cloudtrail:DescribeTrails",
"cloudtrail:LookupEvents",
"cloudtrail:GetTrailStatus",
"cloudtrail:ListTags",
"cloudtrail:StartLogging"
]
effect = "Allow"
resources = ["*"]
}
}

data "aws_iam_policy_document" "cloudwatchlogs_access" {

statement {
actions = [
"logs:List*",
"logs:Get*",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
effect = "Allow"
resources = ["*"]
}
}


resource "aws_iam_role_policy" "lambda_policy_SNS" {
name = "${var.account_name}-security-alert-policy-for-SNS"
policy = "${data.aws_iam_policy_document.sns_access.json}"
role = "${module.role-for-lambda.role_id}"
}


resource "aws_iam_role_policy" "lambda_policy_CT" {
name = "${var.account_name}-security-alert-policy-for-CloudTrail"
policy = "${data.aws_iam_policy_document.cloudtrail_access.json}"
role = "${module.role-for-lambda.role_id}"
}

resource "aws_iam_role_policy" "lambda_policy_CWL" {
name = "${var.account_name}-security-alert-policy-for-CloudWatchLogs"
policy = "${data.aws_iam_policy_document.cloudwatchlogs_access.json}"
role = "${module.role-for-lambda.role_id}"
}

#resource "aws_iam_role_policy_attachment" "cloudwatch_access" {
# policy_arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
# role = "${module.role-for-lambda.role_id}"
#}

#resource "aws_iam_role_policy_attachment" "trail_access" {
# policy_arn = "arn:aws:iam::aws:policy/AWSCloudTrailFullAccess"
# role = "${module.role-for-lambda.role_id}"
#}

19 changes: 19 additions & 0 deletions tf_files/aws/modules/cloudwatch-events/main.tf
@@ -0,0 +1,19 @@

# Let's create the event first
resource "aws_cloudwatch_event_rule" "event_rule" {
name = "${var.cwe_rule_name}"
description = "${var.cwe_rule_description}"

event_pattern = "${var.cwe_rule_pattern}"
}


resource "aws_cloudwatch_event_target" "sns" {
rule = "${aws_cloudwatch_event_rule.event_rule.name}"
# target_id = "SendToLambda"
arn = "${var.cwe_target_arn}"
}




6 changes: 6 additions & 0 deletions tf_files/aws/modules/cloudwatch-events/outputs.tf
@@ -0,0 +1,6 @@

output "event_rule" {
value = "${aws_cloudwatch_event_rule.event_rule.name}"
}


24 changes: 24 additions & 0 deletions tf_files/aws/modules/cloudwatch-events/variables.tf
@@ -0,0 +1,24 @@

variable "cwe_rule_name" {
description = "Name of the rule"
}

variable "cwe_rule_description" {
description = "Brief description of the rule to use"
default = ""
}

variable "cwe_rule_pattern" {
description = "Patter that the rule will use"
default = ""
}

variable "cwe_target_id" {
description = "ID or name to use, if empty, something randon will be used"
default = ""
}

variable "cwe_target_arn" {
description = "ARN of the target that this event will trigger"
}

0 comments on commit c245c6b

Please sign in to comment.