Skip to content
Advertisement

AWS Lambda function with placeholders

I am working on AWS Lambda function for my python function. I have a python function that calls an IAM policy form a file and populates it using the function. This is my function, name of the file is template_utils.py”:

import sys
import json
import time 
import meta_templates
from jinja2 import Template
def lambda_handler(event,context):
  template_data = {}
  template_data["region"] = event.get('region')
  template_data["instance_types"] = event.get('instance_type')
  template_data["ebs_volume_size"] = event.get('ebs_volume_size')
  template_data["meta_template_name"] = event.get('meta_template_name')

  meta_template_dict = getattr(meta_templates, template_data["meta_template_name"])
  meta_template_json = json.dumps(meta_template_dict)
  template_json = Template(meta_template_json).render(template_data)
  return template_json  

template_json = lambda_handler(
  region="us-east-2",
  instance_type="t2.micro",
  ebs_volume_size="20",
  meta_template_name="ec2_policy_meta_template"
)

print(template_json)

This is my policy file named “meta_templates.py”

import json
from jinja2 import Template
ec2_policy_meta_template = { 
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "ec2:RunInstances",
                "Resource": [
                    "arn:aws:ec2:{{region}}::instance/*",
                    "arn:aws:ec2:{{region}}::network-interface/*",
                    "arn:aws:ec2:{{region}}::key-pair/*",
                    "arn:aws:ec2:{{region}}::security-group/*",
                    "arn:aws:ec2:{{region}}::subnet/*",
                    "arn:aws:ec2:{{region}}::volume/*",
                    "arn:aws:ec2:{{region}}::image/ami-*"
                ],
                "Condition": {
                    "ForAllValues:NumericLessThanEquals": {
                        "ec2:VolumeSize": "{{ebs_volume_size}}"
                    },
                    "ForAllValues:StringEquals": {
                        "ec2:InstanceType": "{{instance_type}}"
                    }
                }
            },
            {
                "Sid": "VisualEditor1",
                "Effect": "Allow",
                "Action": [
                    "ec2:TerminateInstances",
                    "ec2:StartInstances",
                    "ec2:StopInstances"
                ],
                "Resource": "arn:aws:ec2:{{region}}::instance/*",
                "Condition": {
                    "ForAllValues:StringEquals": {
                        "ec2:InstanceType": "{{instance_type}}"
                    }
                }
            },
            {
                "Sid": "VisualEditor2",
                "Effect": "Allow",
                "Action": [
                    "ec2:Describe*",
                    "ec2:GetConsole*",
                    "cloudwatch:DescribeAlarms",
                    "iam:ListInstanceProfiles",
                    "cloudwatch:GetMetricStatistics",
                    "ec2:DescribeKeyPairs",
                    "ec2:CreateKeyPair"
                ],
                "Resource": "*",
                "Condition": {
                    "DateGreaterThan": {
                        "aws:CurrentTime": "{{start_time}}"
                    },
                    "DateLessThanEquals": {
                        "aws:CurrentTime": "{{end_time}}"
                    }
                }
            }
        ]
    }

I want to create a lambda handler that does the same thing with the function “template_utils.py”.I’m new to this not sure how to proceed with it.I am getting this error:

Traceback (most recent call last):
  File "/home/pranay/Desktop/work/lambda_handler.py", line 18, in <module>
    template_json = lambda_handler(
TypeError: lambda_handler() got an unexpected keyword argument 'region'

Advertisement

Answer

This should work, providing that you are passing the correct data in the event.

import json


def lambda_handler(event, context):
    template_data = {}
    region = event.get('region')
    instance_type = event.get('instance_type')
    ebs_volume_size = event.get('ebs_volume_size')
    start_time = event.get('start_time')
    end_time = event.get('end_time')

    ec2_policy_meta_template = { 
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Sid": "VisualEditor0",
                  "Effect": "Allow",
                  "Action": "ec2:RunInstances",
                  "Resource": [
                      "arn:aws:ec2:{{region}}::instance/*",
                      "arn:aws:ec2:{{region}}::network-interface/*",
                      "arn:aws:ec2:{{region}}::key-pair/*",
                      "arn:aws:ec2:{{region}}::security-group/*",
                      "arn:aws:ec2:{{region}}::subnet/*",
                      "arn:aws:ec2:{{region}}::volume/*",
                      "arn:aws:ec2:{{region}}::image/ami-*"
                  ],
                  "Condition": {
                      "ForAllValues:NumericLessThanEquals": {
                          "ec2:VolumeSize": "{{ebs_volume_size}}"
                      },
                      "ForAllValues:StringEquals": {
                          "ec2:InstanceType": "{{instance_type}}"
                      }
                  }
              },
              {
                  "Sid": "VisualEditor1",
                  "Effect": "Allow",
                  "Action": [
                      "ec2:TerminateInstances",
                      "ec2:StartInstances",
                      "ec2:StopInstances"
                  ],
                  "Resource": "arn:aws:ec2:{{region}}::instance/*",
                  "Condition": {
                      "ForAllValues:StringEquals": {
                          "ec2:InstanceType": "{{instance_type}}"
                      }
                  }
              },
              {
                  "Sid": "VisualEditor2",
                  "Effect": "Allow",
                  "Action": [
                      "ec2:Describe*",
                      "ec2:GetConsole*",
                      "cloudwatch:DescribeAlarms",
                      "iam:ListInstanceProfiles",
                      "cloudwatch:GetMetricStatistics",
                      "ec2:DescribeKeyPairs",
                      "ec2:CreateKeyPair"
                  ],
                  "Resource": "*",
                  "Condition": {
                      "DateGreaterThan": {
                          "aws:CurrentTime": "{{start_time}}"
                      },
                      "DateLessThanEquals": {
                          "aws:CurrentTime": "{{end_time}}"
                      }
                  }
              }
          ]
      }
      
    json_data = json.dumps(ec2_policy_meta_template)

    # Update resources with a string replacement
    json_data = json_data.replace("{{region}}", region)
    json_data = json_data.replace("{{instance_type}}", instance_type)
    json_data = json_data.replace("{{ebs_volume_size}}", ebs_volume_size)
    json_data = json_data.replace("{{start_time}}", start_time)
    json_data = json_data.replace("{{end_time}}", end_time)
    
    return json_data

This example uses only Python (no third party libraries) it’s not the most elegant solution but its simple. If you want to create additional replacements, just add some additional tags “{{some_text}}” and replace it as shown below.

Here is a test event that works from the lambda console. Test Event

And here is an example of a working invocation working invocation returning json

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement