我想识别terraform执行环境的公共ip,并将其添加到安全组中

我想识别terraform执行环境的公共ip,并将其添加到安全组中,terraform,Terraform,我想确定terraform执行环境的公共IP 并将其添加到aws安全组入站,以防止来自其他环境的访问 目前,我正在手动编辑variables.tf文件中的值 变量.tf variable public_ip_address { default = "xx" } 我想在本地主机上执行“curl ifconfig.co”命令,并根据结果自动设置安全组 有没有办法做到这一点 我可以通过将localexec的结果放入某个变量中来实现 但我不知道怎么做 感谢您阅读我的问题。我能想到的最优雅的

我想确定terraform执行环境的公共IP 并将其添加到aws安全组入站,以防止来自其他环境的访问

目前,我正在手动编辑variables.tf文件中的值

变量.tf

variable public_ip_address {
  default     = "xx"
}
我想在本地主机上执行“curl ifconfig.co”命令,并根据结果自动设置安全组

有没有办法做到这一点

我可以通过将localexec的结果放入某个变量中来实现 但我不知道怎么做


感谢您阅读我的问题。

我能想到的最优雅的解决方案是使用“外部数据源”提供程序

这篇文章就是为了这种目的而写的,人们将本地exec、null资源和vars结合起来,在本地注入一些东西

无论如何,我相信你不用写一个小脚本就可以做到这一点。问题是“外部数据源”希望读取JSON。所以在我的示例中,我只是在程序中构建了一个JSON字符串,然后调用该程序。我相信这可以用echo或jq在一行程序中完成

这是我的main.tf文件:

data "external" "example" {
  program = ["sh", "test.sh" ]
}

output "commandout" {
  value = "${data.external.example.result}"
}
这是我的shell脚本(test.sh):

技术上,一旦出现这种情况,您可以使用:

${data.external.example.result}
作为您的var输入

下面是我使用terraform输出的工作示例

data.external.example: Refreshing state...

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

commandout = {
  ip = 10.0.2.15
}

请注意,
hostname-I
如果您只有一个NIC:)就可以了,否则请使用其他命令或剪切输出以获得所需的结果。

有一种更简单的方法,无需任何脚本即可完成此操作。诀窍在于有一个网站,比如
icanhazip.com
,它可以检索您的IP,所以在您的terraform文件中将其设置为
data

data "http" "myip" {
  url = "http://ipv4.icanhazip.com"
}
无论何时,只要使用
data.http.myip.body
,就可以放置IP,例如:

ingress {
  from_port = 5432
  to_port = 5432
  protocol = "tcp"
  cidr_blocks = ["${chomp(data.http.myip.body)}/32"]
}
  • 注意,我使用terraform
    chomp()
    方法来删除body附带的任何尾随空格或新行

  • 您可以将ipv6与一起使用。请注意使用,因为它可以检索ipv4或ipv6


在Terraform 0.12及更高版本中,您可以使用本机jsondecode和JSONECODE来获得更好的可靠性和长期再现性,而不是依赖字符串操作。作为参考,此实现在Terraform 0.12.16上进行了测试

下面是使用当前可用的较新Terraform方法获取公共ip地址的示例实现。添加输出块是为了提供视觉验证,以确认其是否按预期工作

data "http" "my_public_ip" {
  url = "https://ifconfig.co/json"
  request_headers = {
    Accept = "application/json"
  }
}

locals {
  ifconfig_co_json = jsondecode(data.http.my_public_ip.body)
}

output "my_ip_addr" {
  value = local.ifconfig_co_json.ip
}
如果您想在网络入口规则中利用这一点,您可以执行以下操作(在本例中,icmp用于可测试性,在盲目复制和粘贴的情况下,无需不必要地打开端口):

请注意,所引用的服务的速率限制为每分钟~1个请求,因此如果您的需求超过此限制,您可能最终希望自己托管此服务;或者,如果您需要更可靠的可用性。echoip服务是集装箱化的,因此几乎可以在任何地方托管


太棒了!!我有一个关于main.tf的问题,main.tf是第一次在地形中执行的吗?它是否可以使用main.tf中定义的任意位置设置?Terraform在工作区中加载*.tf,您的值需要在当前工作区中可用或通过远程数据导入。@Anshupratek您能看到我的新问题吗?我还没有解决根本问题。链接在这里
hostname-I
显示NIC的所有ip地址,但这仅显示任何专用网络上的本地ip地址,除非您没有被NAT'D in。如果你是NAT'ed,你的系统根本不可能知道外部的公共IP,所以你需要从外部世界获取它。谢天谢地,有相关的服务,因此您最好运行类似于
curl ifconfig.co
的程序,它将返回您连接到它的IP地址。您将如何使用新值更新现有的安全组?如果用例中的每个人都希望在相同的安全性中使用他们自己的IP呢group@Fo. 不幸的是,Amazon返回的是
200 OK
,但不是
text/*
application/json
内容类型头,这是terraform的http数据源所必需的:@kevlened这可以做到如果您使用它连接到db实例,别忘了让db实例可访问!我会添加一个安全警告。您不应该信任远程IP服务。。。您应该检查生成的IP是否属于授权的IP列表/范围。这将返回ipv6如何传递-4标志以获取v4?
data "http" "my_public_ip" {
  url = "https://ifconfig.co/json"
  request_headers = {
    Accept = "application/json"
  }
}

locals {
  ifconfig_co_json = jsondecode(data.http.my_public_ip.body)
}

output "my_ip_addr" {
  value = local.ifconfig_co_json.ip
}
ingress {
  from_port = 0
  to_port = 0
  protocol = "-1"
  cidr_blocks = ["${local.ifconfig_co_json.ip}/32"]
}