Terraform/lambda/IAM 根据标签停止 ec2

Posted

技术标签:

【中文标题】Terraform/lambda/IAM 根据标签停止 ec2【英文标题】:Terraform/lambda/IAM to stop ec2 based on a tag 【发布时间】:2021-05-15 10:40:31 【问题描述】:

这是任何尝试测试它的人的资源https://cloudywithachanceofbigdata.com/really-simple-terraform-infrastructure-automation-using-aws-lambda/。

我的 tf 脚本创建:

IAM 角色和 Lambda 函数的关联策略 Lambda 函数 Cloudwatch 事件规则和触发器

我的 terraform 版本:

Terraform v0.13.4

我的 main.tf 如下:

#
# Module Provider
#

provider "aws" 
    region = "us-west-1"
    shared_credentials_file = "~/.aws/credentials"
    profile                 = "default"


#
# Create IAM Role and Policy for Lambda Function
#

resource "aws_iam_role" "lambda_stop_ec2" 
  name = "lambda_stop_ec2"
  assume_role_policy = <<EOF

  "Version": "2012-10-17",
  "Statement": [
    
      "Sid": "",
      "Effect": "Allow",
      "Principal": 
        "Service": [
          "lambda.amazonaws.com"
        ]
      ,
      "Action": "sts:AssumeRole"
    
  ]

EOF


resource "aws_iam_role_policy" "lamdba_ec2_shutdown_policy" 
  name = "lamdba_ec2_shutdown_policy"
  role = "$aws_iam_role.lambda_stop_ec2.id"
  policy = <<EOF

  "Version": "2012-10-17",
  "Statement": [
    
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*"
    ,
    
      "Effect": "Allow",
      "Action": [
        "ec2:Stop*",
        "ec2:DescribeInstances"
      ],
      "Resource": "*"
    
  ]

EOF


#
# Create ZIP Archive for Function Source Code
#

data "archive_file" "lambda_stop_ec2_zip" 
  type = "zip"
  output_path = "/home/test/scheduler/repo/simple-lambda-ec2-scheduler/lambda_stop_ec2_zip"
  source_dir = "/home/test/scheduler/repo/simple-lambda-ec2-scheduler/function_source_code/"


#
# Create Lambda Function
#
 
resource "aws_lambda_function" "lambda_stop_ec2" 
  filename = "lambda_stop_ec2_zip"
  function_name    = "lambda_stop_ec2"
  timeout          = 10  
  role             = "$aws_iam_role.lambda_stop_ec2.arn"
  handler          = "lambda_stop_ec2.lambda_handler"
  runtime          = "python3.8"


#
# Create CloudWatch Event Rule
#

resource "aws_cloudwatch_event_rule" "stop_ec2_event_rule" 
  name        = "stop-ec2-event-rule"
  description = "Stop running EC2 instance at a specified time each day"
  schedule_expression = "$var.schedule_expression"


#
# Create CloudWatch Event Target
#

resource "aws_cloudwatch_event_target" "stop_ec2_event_rule_target" 
  rule      = "$aws_cloudwatch_event_rule.stop_ec2_event_rule.name"
  target_id = "TriggerLambdaFunction"
  arn       = "$aws_lambda_function.lambda_stop_ec2.arn"
  input     = "\"name\":\"$var.name\""


#
# Add Lamdba Permission
#

resource "aws_lambda_permission" "allow_cloudwatch" 
  statement_id  = "AllowExecutionFromCloudWatch"
  action        = "lambda:InvokeFunction"
  function_name = "$aws_lambda_function.lambda_stop_ec2.function_name"
  principal     = "events.amazonaws.com"
  source_arn    = "$aws_cloudwatch_event_rule.stop_ec2_event_rule.arn"

我的 terraform.tfvars:

schedule_expression = "cron(0 17 * * ? *)"
name = "instanceScheduler"

我的变量.tf:

variable "schedule_expression" 
variable "name" 

我的函数源代码/lambda_stop_ec2.py

import boto3
region = 'us-west-1'

def lambda_handler(event, context):
    name = event["name"]
    print("stopping all instances in the %s name" % (name))
    ec2 = boto3.client('ec2', region_name=region)
    response = ec2.describe_instances(
        Filters=[
            
                'Name': 'tag:Name',
                'Values': [name]
            
        ]
    )
    for reservation in response["Reservations"]:
        for instance in reservation["Instances"]:
            print("instance [%s] is in [%s] state" % (instance["InstanceId"], instance["State"]["Name"]))
            if instance["State"]["Name"] == "running":
                print("stopping instance [%s]" % (instance["InstanceId"]))
                ec2.stop_instances(InstanceIds=[instance["InstanceId"]])
                print("instance [%s] stopped" % (instance["InstanceId"]))

我的运行命令:

terraform init
terraform apply

我得到了什么:

Plan: 6 to add, 0 to change, 0 to destroy.


Warning: Interpolation-only expressions are deprecated

  on main.tf line 38, in resource "aws_iam_role_policy" "lamdba_ec2_shutdown_policy":
  38:   role = "$aws_iam_role.lambda_stop_ec2.id"

Terraform 0.11 and earlier required all non-constant expressions to be
provided via interpolation syntax, but this pattern is now deprecated. To
silence this warning, remove the "$ sequence from the start and the "
sequence from the end of this expression, leaving just the inner expression.

Template interpolation syntax is still used to construct strings from
expressions when the template includes multiple interpolation sequences or a
mixture of literal strings and interpolations. This deprecation applies only
to templates that consist entirely of a single interpolation sequence.

(and 6 more similar warnings elsewhere)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_cloudwatch_event_rule.stop_ec2_event_rule: Creating...
aws_iam_role.lambda_stop_ec2: Creating...
aws_iam_role.lambda_stop_ec2: Creation complete after 1s [id=lambda_stop_ec2]
aws_iam_role_policy.lamdba_ec2_shutdown_policy: Creating...
aws_lambda_function.lambda_stop_ec2: Creating...
aws_cloudwatch_event_rule.stop_ec2_event_rule: Creation complete after 2s [id=stop-ec2-event-rule]
aws_lambda_function.lambda_stop_ec2: Still creating... [10s elapsed]
aws_lambda_function.lambda_stop_ec2: Creation complete after 16s [id=lambda_stop_ec2]
aws_lambda_permission.allow_cloudwatch: Creating...
aws_cloudwatch_event_target.stop_ec2_event_rule_target: Creating...
aws_lambda_permission.allow_cloudwatch: Creation complete after 1s [id=AllowExecutionFromCloudWatch]
aws_cloudwatch_event_target.stop_ec2_event_rule_target: Creation complete after 1s [id=stop-ec2-event-rule-TriggerLambdaFunction]

Error: Error putting IAM role policy lamdba_ec2_shutdown_policy: MalformedPolicyDocument: Partition "aws" is not valid for resource "arn:aws:logs:*:*:*".
        status code: 400, request id: b2e4b11e-da82-4b1d-b482-8cc2a3afd242

请帮忙!!

【问题讨论】:

【参考方案1】:

在https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-identity-based-access-control-cwl.html 显示的策略示例中

资源是"arn:aws:logs:*:*:*"

请参见 3 个星号。你的只有 1 个。我在 IAM Policy Simulator (https://policysim.aws.amazon.com/) 测试了你的策略,由于缺少星号,它无效

完整的政策示例:


  "Version": "2012-10-17",
  "Statement": [
    
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogStreams"
    ],
      "Resource": [
        "arn:aws:logs:*:*:*"
    ]
  
 ]

【讨论】:

感谢您的评论。我已根据您的评论对其进行了更新,这是新的错误Error: Error putting IAM role policy lamdba_ec2_shutdown_policy: MalformedPolicyDocument: Partition "aws" is not valid for resource "arn:aws:logs:*:*:*". status code: 400, request id: 0584c5a5-eae5-4ebb-9300-70e3a7570a5c 您是否在 AWS GovCloud 中运行它? 是的,我想:)"Resource": "arn:aws-us-gov:logs:*:*:*"

以上是关于Terraform/lambda/IAM 根据标签停止 ec2的主要内容,如果未能解决你的问题,请参考以下文章

无法根据标签的文本动态调整标签的高度

用于根据上标签内容向下移动标签的自动布局约束

如何根据h标签的宽度设置p标签的宽度

根据子弹级别将li标签替换为不同的标签

使用 XSLT 根据 xml 中特定标签的数量动态添加 XML 标签

根据 UITableViewCell 标签高度和宽度调整背景图片大小