如何使用 Terraform 传递 AssumeRole 并将 SSM 文档与 EC2 关联

Posted

技术标签:

【中文标题】如何使用 Terraform 传递 AssumeRole 并将 SSM 文档与 EC2 关联【英文标题】:How to pass AssumeRole and associate SSM Document with EC2 using Terraform 【发布时间】:2021-12-11 05:23:08 【问题描述】:

我正在尝试将 SSM 文档(将 linux 服务器与 AD 域连接)与 EC2 实例相关联。

我在关联过程中收到以下错误 -

aws_ssm_association.rhel: Creating...
╷
│ Error: Error creating SSM association: ValidationException: The assume role is invalid.
│       status code: 400, request id: 3e2e23f0-da9e-4d0d-947f-2f121aa653e9
│ 
│   with aws_ssm_association.rhel,
│   on ssm.tf line 10, in resource "aws_ssm_association" "rhel":
│   10: resource "aws_ssm_association" "rhel" 

这是我的 Terraform 代码 -

main.tf

provider "aws" 
  region              = "us-west-2"
  allowed_account_ids = ["1234"]

  assume_role 
    role_arn = "arn:aws:iam::1234:role/my-role"
  


terraform 
  required_version = "= 1.0.9"


ec2.tf

resource "aws_key_pair" "rhel" 
  key_name_prefix = "rhel_domain_join_test"
  public_key      = "ssh-rsa AMAMAMMMxxxx"


resource "aws_instance" "rhel" 
  ami                    = "ami-0b28dfc7adc3xxx" # us-west-2
  instance_type          = "t3.medium"
  subnet_id              = "subnet-023db3ebxxx"
  iam_instance_profile   = aws_iam_instance_profile.rhel_instance_profile.id
  vpc_security_group_ids = ["sg-077f9f9aceexxxx"]
  key_name               = aws_key_pair.rhel.id

  tags = 
    Name = "w2domainjointestpoc"
  


iam.tf

resource "aws_iam_instance_profile" "rhel_instance_profile" 
  name_prefix = "rhel_instance_profile"
  role        = aws_iam_role.rhel_instance_role.name


resource "aws_iam_role" "rhel_instance_role" 
  name_prefix        = "rhel_instance_role"
  path               = "/"
  assume_role_policy = data.aws_iam_policy_document.ssm_role_policy.json


resource "aws_iam_role_policy_attachment" "rhel_instance" 
  role       = aws_iam_role.rhel_instance_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole"


resource "aws_iam_role_policy_attachment" "rhel_instance_2" 
  role       = aws_iam_role.rhel_instance_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"


resource "aws_iam_role_policy_attachment" "ec2-attach" 
  role       = aws_iam_role.rhel_instance_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2FullAccess"



resource "aws_iam_policy" "ssm_role_pas-s-role" 
  name_prefix = "ssm_automation"
  description = "My test policy"
  policy      = data.aws_iam_policy_document.ssm_role_pas-s-role.json


resource "aws_iam_role_policy_attachment" "ssm_role_pas-s-role" 
  role       = aws_iam_role.rhel_instance_role.name
  policy_arn = aws_iam_policy.ssm_role_pas-s-role.arn

data.tf

data "aws_iam_policy_document" "ssm_role_policy" 
  statement 
    actions = ["sts:AssumeRole"]

    principals 
      type        = "Service"
      identifiers = ["ec2.amazonaws.com", "ssm.amazonaws.com"]
    
  



data "aws_iam_policy_document" "ssm_role_pas-s-role" 
  statement 
    actions   = ["iam:GetRole", "iam:PassRole"]
    resources = [aws_iam_role.rhel_instance_role.arn]
  

ssm.tf

resource "aws_ssm_document" "rhel_domain_join_document" 
  name            = "rhel_domain_join_document"
  document_format = "JSON"
  document_type   = "Automation"


  content = file("$path.module/redhat_linux_launch_automation_document.json")


resource "aws_ssm_association" "rhel" 
  name = aws_ssm_document.rhel_domain_join_document.name

  targets 
    key    = "InstanceIds"
    values = [aws_instance.rhel.id]
  

你能帮我理解我在这里缺少什么吗?

谢谢

【问题讨论】:

什么是redhat_linux_launch_automation_document.json 这是一个SSM文件-github.com/tensult/terraform/blob/master/aws/…@Marcin 【参考方案1】:

我认为您混淆了 SSM 文档类型。对于 SSM 状态管理器,您可以使用 三种 documents:

    政策 命令 自动化

您的redhat_linux_launch_automation_document.json 是一个自动化。因此,targets 块中的 aws_ssm_association.rhel 并不完全适用。 targets 块仅适用于前两种文档类型或速率控制Automation

对于自动化类型的简单执行,您只需在aws_ssm_association.rhel 中提供parameters,假设您不需要任何速率或计划执行控制。此外,您的 redhat_linux_launch_automation_document.json担任任何角色

应该是这样的:

redhat_linux_launch_automation_document.json(部分视图)

添加角色AutomationAssumeRole


    "description": "Launch Automation for RedHat Linux instance",
    "schemaVersion": "0.3",
    "assumeRole": "AutomationAssumeRole",    
    "parameters": 
        "instanceIds": 
            "type": "StringList",
            "description": "InstanceIds to run launch setup"
        ,
        "AutomationAssumeRole": 
          "default": "",
          "type": "String",
          "description": "(Optional) The ARN of the role that allows Automation to perform the actions on your behalf."
                
    ,

ma​​in.tf

创建 SSM 角色:

resource "aws_iam_role" "ssm" 
  path               = "/"
  assume_role_policy = <<EOL

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

EOL

  managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole"]

  inline_policy 
    name = "my_inline_policy"

    policy = jsonencode(
      Version = "2012-10-17"
      Statement = [
        
          Action   = ["iam:PassRole"]
          Effect   = "Allow"
          Resource = "*"
        ,
      ]
    )
  


最后修复aws_ssm_association.rhel:

resource "aws_ssm_association" "rhel" 

  name = aws_ssm_document.rhel_domain_join_document.name
  
  parameters = 
      AutomationAssumeRole = aws_iam_role.ssm.arn
      instanceIds = aws_instance.rhel.id
    

注意:我的回答仅针对您的错误消息。我没有检查您的自动化文档是否真的有效。为此,您可能需要创建新问题。

【讨论】:

很好的答案@marcin

以上是关于如何使用 Terraform 传递 AssumeRole 并将 SSM 文档与 EC2 关联的主要内容,如果未能解决你的问题,请参考以下文章

如何将使用 cidrsubnets 的子网的 CIDR 范围传递给 Terraform 版本 0.14 中的 VPC 模块

如何使用 Terraform 传递 AssumeRole 并将 SSM 文档与 EC2 关联

Terraform:如何将变量传递给 user_data 初始化脚本

如何从 Terraform 输出中传递值而不将其放入 tfvars 文件中

通过 terraform 在 cloud init 中传递 python 脚本

如何在 Terraform 变量中连接 S3 存储桶名称并将其传递给主 tf 文件