You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Terratest的init和plan验证Terraform安全组规则端口

用Terratest精准验证Terraform安全组规则(仅Init/Plan)

不用部署资源,直接解析Terraform Plan的结构化输出,就能精准校验安全组的入站、出站端口,比模糊的字符串匹配靠谱得多。

实现步骤

1. 生成并解析Terraform Plan的JSON输出

通过Terratest执行terraform init和terraform plan,并将计划输出转为JSON格式,直接提取结构化的安全组规则数据,避免靠字符串匹配猜测内容。

2. 提取安全组规则的端口信息

从JSON输出中定位到目标安全组的ingress和egress字段,解析其中的端口范围字段(比如AWS安全组用from_port和to_port,不同云厂商字段可能有差异)。

3. 编写精准断言

用Terratest集成的assert包直接校验端口值是否符合预期,比如检查入站是否仅开放指定端口、出站端口范围是否合规。

代码示例

package test

import (
	"encoding/json"
	"testing"

	"github.com/gruntwork-io/terratest/modules/terraform"
	"github.com/stretchr/testify/assert"
)

// 仅定义Plan中需要用到的结构体字段,可按需扩展
type TerraformPlan struct {
	ResourceChanges []struct {
		Address string `json:"address"`
		Change  struct {
			After map[string]interface{} `json:"after"`
		} `json:"change"`
	} `json:"resource_changes"`
}

func TestSecurityGroupRules(t *testing.T) {
	t.Parallel()

	// 配置Terraform模块路径
	terraformOpts := &terraform.Options{
		TerraformDir: "../path/to/your/terraform/module",
	}

	// 执行init和plan,生成plan文件
	planFilePath := terraform.InitAndPlanWithOpts(t, terraformOpts, terraform.WithPlanOut("plan.out"))

	// 将plan文件转为JSON格式输出
	planJSON := terraform.ShowPlanJSON(t, terraformOpts, planFilePath)

	// 解析JSON到结构体
	var plan TerraformPlan
	err := json.Unmarshal([]byte(planJSON), &plan)
	assert.NoError(t, err)

	// 定位目标安全组
	targetSGAddress := "aws_security_group.your_sg_name"
	var targetSG map[string]interface{}
	for _, rc := range plan.ResourceChanges {
		if rc.Address == targetSGAddress {
			targetSG = rc.Change.After
			break
		}
	}
	assert.NotNil(t, targetSG, "目标安全组未在Plan中找到")

	// 校验入站规则端口
	ingressRules := targetSG["ingress"].([]interface{})
	expectedIngressPorts := []int{22, 443}
	for _, rule := range ingressRules {
		ruleMap := rule.(map[string]interface{})
		fromPort := int(ruleMap["from_port"].(float64))
		toPort := int(ruleMap["to_port"].(float64))
		// 验证端口在预期列表内,且为单一端口(from=to)
		assert.Contains(t, expectedIngressPorts, fromPort)
		assert.Equal(t, fromPort, toPort)
	}

	// 校验出站规则(示例:允许所有端口)
	egressRules := targetSG["egress"].([]interface{})
	for _, rule := range egressRules {
		ruleMap := rule.(map[string]interface{})
		fromPort := int(ruleMap["from_port"].(float64))
		toPort := int(ruleMap["to_port"].(float64))
		assert.Equal(t, 0, fromPort)
		assert.Equal(t, 0, toPort) // AWS安全组中0代表所有端口
	}
}

关键说明

  • 结构体TerraformPlan可根据实际Plan的JSON结构扩展字段,比如需要校验源IP、协议等规则时,只需补充对应字段即可。
  • 不同云厂商的安全组字段可能不同:比如Azure用destination_port_ranges,需要对应调整解析逻辑。
  • 用terraform.ShowPlanJSON直接获取结构化输出,比自行执行shell命令解析更稳定可靠。

内容的提问来源于stack exchange,提问作者Bunny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:06:20