The Inner Circle

 View Only

Remediating Noncompliant AWS Resources using AWS Native Tools

By Devon Artis posted Aug 19, 2020 08:05:26 AM

  
In this post, I have added a fictitious scenario where I will define the problem and develop the simple solution that outlines an automated workflow that utilizes the tools that I wrote about in my first post How To Validate Internal Security Compliance With AWS Native Tools.

Here is the scenario, a company called WantToBeAgile, Inc has started their migration to AWS Public Cloud. The Security Compliance team has mandated that all resources in AWS be tagged. If a resource is not tagged a Jira Issue should be created and assigned to the SOC team.

The Cloud Operations team has already enabled AWS Config in all accounts as their Cloud Asset and Resource management tool. The organization has requested that the Cloud Security Engineers implement a solution that will be used as the automated baseline.

AWS Config

troinArtis-AWS-Config.png


In Jira, create an API token and make sure that you copy the key, as this key will be used in the next step.

JiraTroinArtis.png

AWS System Manager Parameter Store provides secure hierarchical storage for configuration data management and secrets management. You can store data such as passwords, database strings, and license codes as parameter values. I will be using it to store the API key.


Store your Jira Token in AWS SSM Parameter Store



# Store your Jira Token in Parameter Store 

resource "aws_ssm_parameter" "paramtoken" {
  name        = "jiraToken"
  description = "Jira Token used in the AWS Config Create Jira Issue"
  value       =  var.jiraToken
  type        = "SecureString"
}

Create IAM Role that will be used for the Lambda Function

# IAM Role For Lambda Functions
resource "aws_iam_role" "iam_for_lambda" {
  name = "iam_for_lambda"


  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}



Create the lambda function that will be used for SSM Document

# Archive the python code for that will be used for the lambda function
data "archive_file" "lambda_zip" {
  type = "zip"
  source_file = "../index.py"
  output_path = "lambda_function.zip"
}


# Create your lambda function


resource "aws_lambda_function" "ssm_lambda" {
  filename = "lambda_function.zip"
  function_name = var.lambda_name
  role = "${aws_iam_role.iam_for_lambda.arn}"


  handler = "index.handler"
  source_code_hash = "${data.archive_file.lambda_zip.output_base64sha256}"
  runtime = "python2.7"
  depends_on = [
    "aws_iam_role_policy_attachment.lambda_ssm",
    "aws_iam_role_policy_attachment.lambda_logs",
    "aws_cloudwatch_log_group.createJiraIssuelogs"
  ]
}

resource "aws_cloudwatch_log_group" "createJiraIssuelogs" {
  name = "/aws/lambda/${var.lambda_name}"
  retention_in_days = 14
}



resource "aws_iam_policy" "policy_logging" {
  name = "lambda_logging"
  path = "/"
  description = "IAM policy for logging from a lambda"


  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*",
      "Effect": "Allow"
    }
  ]
}
EOF
}


resource "aws_iam_role_policy_attachment" "lambda_logs" {
  role       = "${aws_iam_role.iam_for_lambda.name}"
  policy_arn = "${aws_iam_policy.policy_logging.arn}"
}


resource "aws_iam_policy" "policy_ssm" {
  name        = "lambda_readssm"
  path        = "/"
  description = "IAM policy for SSM Paramater Store for a lambda"


  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
           
            "Effect": "Allow",
            "Action": "ssm:*",
            "Resource": "*"
        }
    ]
}
EOF
}


resource "aws_iam_role_policy_attachment" "lambda_ssm" {
  role = "${aws_iam_role.iam_for_lambda.name}"
  policy_arn = "${aws_iam_policy.policy_ssm.arn}"
}



Create the SSM Document that you will use with AWS Config

# Create SSM Document that will be used in AWS Config


resource "aws_ssm_document" "jiraDocument" {
  content = <<EOF
{
  "description": "Creates a Jira issue.",
  "schemaVersion": "0.3",
  "assumeRole": "{{ AutomationAssumeRole }}",
  "parameters": {
    "JiraUsername": {
      "type": "String",
      "description": "(Required) The name of the user the issue will be created with."
    },
    "SSMParameterName": {
      "type": "String",
      "description": "(Required) The name of an encrypted SSM Parameter containing the API key or password for the Jira user."
    },
    "JiraURL": {
      "type": "String",
      "description": "(Required) The url of the Jira instance."
    },
    "ProjectKey": {
      "type": "String",
      "description": "(Required) The key of the project the issue should be created in."
    },
    "IssueSummary": {
      "type": "String",
      "description": "(Required) A brief summary of the issue."
    },
    "IssueDescription": {
      "type": "String",
      "description": "(Required) A detailed description of the issue."
    },
    "IssueTypeName": {
      "type": "String",
      "description": "(Required) The name of the type of issue you want to create (ex. Task, Sub-task, Bug, etc)."
    },
    "PriorityName": {
      "type": "String",
      "description": "(Optional) The name of the priority of the issue.",
      "default": ""
    },
    "AssigneeName": {
      "type": "String",
      "description": "(Optional) The username of the person the issue should be assigned to.",
      "default": ""
    },
    "DueDate": {
      "type": "String",
      "description": "(Optional) The due date for the issue in yyyy-mm-dd format.",
      "default": ""
    },
    "CreatedBy": {
      "type": "String",
      "description": "(Optional) The due date for the issue in yyyy-mm-dd format.",
      "default": ""
    },
    "LambdaAssumeRole": {
      "type": "String",
      "description": "(Optional) The ARN of the role that allows Lambda created by Automation to perform the actions on your behalf. If not specified a transient role will be created to execute the Lambda function.",
      "default": ""
    },
    "AutomationAssumeRole": {
      "type": "String",
      "description": "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf. ",
      "default": ""
    }
  },
  "mainSteps": [
    {
      "name": "createJiraIssue",
      "action": "aws:invokeLambdaFunction",
      "inputs": {
        "FunctionName": "createComplainceJiraIssue",
        "Payload": "{\"JiraUsername\": \"{{JiraUsername}}\", \"SSMParameterName\": \"{{SSMParameterName}}\", \"JiraURL\": \"{{JiraURL}}\", \"ProjectKey\": \"{{ProjectKey}}\", \"IssueSummary\": \"{{IssueSummary}}\", \"IssueDescription\": \"{{IssueDescription}}\", \"IssueTypeName\": \"{{IssueTypeName}}\", \"PriorityName\": \"{{PriorityName}}\", \"AssigneeName\": \"{{AssigneeName}}\", \"DueDate\": \"{{DueDate}}\"}"
      }
    }
  ],
  "outputs": [
    "createJiraIssue.Payload"
  ]
}
EOF
  document_type   = "Automation"
  name            = "Security-ComplainceWorkflowDemo"
  document_format = "JSON"
}

 

Now that the automation system has been built the last thing we have to do is choose the SSM document that we created in the code above.


Setting Up AWS Config
  1. Sign in to the AWS Management Console and open the AWS Config console at https://console.aws.amazon.com/config/.
  2. Choose Rules on the left, then on the Rules page in the search field, type in "required-tags"
  3. On the Edit Name of the rule page, in the Choose remediation action section, select Security-ComplainceWorkflowDemo. Fill out the required fields.
  4. Choose Save.

troinArtis-COmplaince.png


Now when a "required-tag" resource violation has occurred the "Security-ComplianceWorkflowDemo." remediation action will be executed.

0 comments
23 views
placeholder for permalink
Placeholder for comments