Skip to content

Commit 80ec2a0

Browse files
authored
feat: security group - support protocol template values (#1315)
* fix: sg - datasource support protocol template * feat: sg lite rule - support protocol template * changelog 1315 add * Update 1315.txt * fix: service sg lite regexp convert
1 parent da52eb0 commit 80ec2a0

File tree

4 files changed

+108
-46
lines changed

4 files changed

+108
-46
lines changed

.changelog/1315.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:bug
2+
data-source/tencentcloud_security_groups: support protocol template readings
3+
```
4+
5+
```release-note:enhancement
6+
resource/tencentcloud_security_group_lite_rule: support protocol template creating/updating
7+
```

tencentcloud/resource_tc_security_group_lite_rule.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ resource "tencentcloud_security_group_lite_rule" "foo" {
2020
"ACCEPT#sg-7ixn3foj#80-90#TCP",
2121
"ACCEPT#ipm-epjq5kn0#80-90#TCP",
2222
"ACCEPT#ipmg-3loavam6#80-90#TCP",
23+
"ACCEPT#0.0.0.0/0##ppm-xxxxxxxx"
24+
"ACCEPT#0.0.0.0/0##ppmg-xxxxxxxx"
2325
]
2426
2527
egress = [
@@ -68,13 +70,13 @@ func resourceTencentCloudSecurityGroupLiteRule() *schema.Resource {
6870
Type: schema.TypeList,
6971
Optional: true,
7072
Elem: &schema.Schema{Type: schema.TypeString},
71-
Description: "Ingress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP` and `ALL`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.",
73+
Description: "Ingress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP`, `ALL` and `ppm(g?)-xxxxxxxx`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.",
7274
},
7375
"egress": {
7476
Type: schema.TypeList,
7577
Optional: true,
7678
Elem: &schema.Schema{Type: schema.TypeString},
77-
Description: "Egress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP` and `ALL`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.",
79+
Description: "Egress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP`, `ALL` and `ppm(g?)-xxxxxxxx`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.",
7880
},
7981
},
8082
}

tencentcloud/service_tencentcloud_vpc.go

Lines changed: 93 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,23 @@ type VpcRouteTableBasicInfo struct {
7676
}
7777

7878
type VpcSecurityGroupLiteRule struct {
79-
action string
80-
cidrIp string
81-
port string
82-
protocol string
83-
addressId string
84-
addressGroupId string
85-
securityGroupId string
86-
}
87-
88-
var securityGroupIdRE = regexp.MustCompile(`^sg-\\w{8}$`)
89-
var ipAddressIdRE = regexp.MustCompile(`^ipm-\\w{8}$`)
90-
var ipAddressGroupIdRE = regexp.MustCompile(`^ipmg-\\w{8}$`)
79+
action string
80+
cidrIp string
81+
port string
82+
protocol string
83+
addressId string
84+
addressGroupId string
85+
securityGroupId string
86+
protocolTemplateId string
87+
protocolTemplateGroupId string
88+
}
89+
90+
var securityGroupIdRE = regexp.MustCompile(`^sg-\w{8}$`)
91+
var ipAddressIdRE = regexp.MustCompile(`^ipm-\w{8}$`)
92+
var ipAddressGroupIdRE = regexp.MustCompile(`^ipmg-\w{8}$`)
93+
var protocolTemplateRE = regexp.MustCompile(`^ppmg?-\w{8}$`)
94+
var protocolTemplateIdRE = regexp.MustCompile(`^ppm-\w{8}$`)
95+
var protocolTemplateGroupIdRE = regexp.MustCompile(`^ppmg-\w{8}$`)
9196
var portRE = regexp.MustCompile(`^(\d{1,5},)*\d{1,5}$|^\d{1,5}-\d{1,5}$`)
9297

9398
// acl rule
@@ -121,7 +126,15 @@ func (rule VpcSecurityGroupLiteRule) String() string {
121126
source = rule.addressGroupId
122127
}
123128

124-
return fmt.Sprintf("%s#%s#%s#%s", rule.action, source, rule.port, rule.protocol)
129+
protocol := rule.protocol
130+
131+
if protocol == "" && rule.protocolTemplateId != "" {
132+
protocol = rule.protocolTemplateId
133+
} else if protocol == "" && rule.protocolTemplateGroupId != "" {
134+
protocol = rule.protocolTemplateGroupId
135+
}
136+
137+
return fmt.Sprintf("%s#%s#%s#%s", rule.action, source, rule.port, protocol)
125138
}
126139

127140
func getSecurityGroupPolicies(rules []VpcSecurityGroupLiteRule) []*vpc.SecurityGroupPolicy {
@@ -130,8 +143,7 @@ func getSecurityGroupPolicies(rules []VpcSecurityGroupLiteRule) []*vpc.SecurityG
130143
for i := range rules {
131144
rule := rules[i]
132145
policy := &vpc.SecurityGroupPolicy{
133-
Protocol: &rule.protocol,
134-
Action: &rule.action,
146+
Action: &rule.action,
135147
}
136148

137149
if rule.securityGroupId != "" {
@@ -148,7 +160,23 @@ func getSecurityGroupPolicies(rules []VpcSecurityGroupLiteRule) []*vpc.SecurityG
148160
policy.CidrBlock = &rule.cidrIp
149161
}
150162

151-
if rule.port != "" {
163+
usingProtocolTemplate := rule.protocolTemplateId != "" || rule.protocolTemplateGroupId != ""
164+
165+
if usingProtocolTemplate {
166+
policy.ServiceTemplate = &vpc.ServiceTemplateSpecification{}
167+
if rule.protocolTemplateId != "" {
168+
policy.ServiceTemplate.ServiceId = &rule.protocolTemplateId
169+
}
170+
if rule.protocolTemplateGroupId != "" {
171+
policy.ServiceTemplate.ServiceGroupId = &rule.protocolTemplateGroupId
172+
}
173+
}
174+
175+
if !usingProtocolTemplate {
176+
policy.Protocol = &rule.protocol
177+
}
178+
179+
if !usingProtocolTemplate && rule.port != "" {
152180
policy.Port = &rule.port
153181
}
154182

@@ -1726,8 +1754,6 @@ func (me *VpcService) DescribeSecurityGroupPolices(ctx context.Context, sgId str
17261754

17271755
for _, in := range policySet.Ingress {
17281756
if nilFields := CheckNil(in, map[string]string{
1729-
"Protocol": "protocol",
1730-
"Port": "port",
17311757
"Action": "action",
17321758
"SecurityGroupId": "nested security group id",
17331759
}); len(nilFields) > 0 {
@@ -1737,7 +1763,7 @@ func (me *VpcService) DescribeSecurityGroupPolices(ctx context.Context, sgId str
17371763

17381764
liteRule := VpcSecurityGroupLiteRule{
17391765
//protocol: strings.ToUpper(*in.Protocol),
1740-
port: *in.Port,
1766+
//port: *in.Port,
17411767
cidrIp: *in.CidrBlock,
17421768
action: *in.Action,
17431769
securityGroupId: *in.SecurityGroupId,
@@ -1747,18 +1773,25 @@ func (me *VpcService) DescribeSecurityGroupPolices(ctx context.Context, sgId str
17471773
liteRule.protocol = strings.ToUpper(*in.Protocol)
17481774
}
17491775

1776+
if in.Port != nil {
1777+
liteRule.port = *in.Port
1778+
}
1779+
17501780
if in.AddressTemplate != nil {
17511781
liteRule.addressId = *in.AddressTemplate.AddressId
17521782
liteRule.addressGroupId = *in.AddressTemplate.AddressGroupId
17531783
}
17541784

1785+
if in.ServiceTemplate != nil {
1786+
liteRule.protocolTemplateId = *in.ServiceTemplate.ServiceId
1787+
liteRule.protocolTemplateGroupId = *in.ServiceTemplate.ServiceGroupId
1788+
}
1789+
17551790
ingress = append(ingress, liteRule)
17561791
}
17571792

17581793
for _, eg := range policySet.Egress {
17591794
if nilFields := CheckNil(eg, map[string]string{
1760-
"Protocol": "protocol",
1761-
"Port": "port",
17621795
"Action": "action",
17631796
"SecurityGroupId": "nested security group id",
17641797
}); len(nilFields) > 0 {
@@ -1767,18 +1800,29 @@ func (me *VpcService) DescribeSecurityGroupPolices(ctx context.Context, sgId str
17671800
}
17681801

17691802
liteRule := VpcSecurityGroupLiteRule{
1770-
protocol: strings.ToUpper(*eg.Protocol),
1771-
port: *eg.Port,
17721803
action: *eg.Action,
17731804
cidrIp: *eg.CidrBlock,
17741805
securityGroupId: *eg.SecurityGroupId,
17751806
}
17761807

1808+
if eg.Port != nil {
1809+
liteRule.port = *eg.Port
1810+
}
1811+
1812+
if eg.Protocol != nil {
1813+
liteRule.protocol = strings.ToUpper(*eg.Protocol)
1814+
}
1815+
17771816
if eg.AddressTemplate != nil {
17781817
liteRule.addressId = *eg.AddressTemplate.AddressId
17791818
liteRule.addressGroupId = *eg.AddressTemplate.AddressGroupId
17801819
}
17811820

1821+
if eg.ServiceTemplate != nil {
1822+
liteRule.protocolTemplateId = *eg.ServiceTemplate.ServiceId
1823+
liteRule.protocolTemplateGroupId = *eg.ServiceTemplate.ServiceGroupId
1824+
}
1825+
17821826
egress = append(egress, liteRule)
17831827
}
17841828

@@ -2023,12 +2067,14 @@ func parseRule(str string) (liteRule VpcSecurityGroupLiteRule, err error) {
20232067
}
20242068

20252069
var (
2026-
source string
2070+
source string
2071+
port string
2072+
protocol string
20272073
// source is "sg-xxxxxx" / "ipm-xxxxxx" / "ipmg-xxxxxx" formatted
20282074
isInstanceIdSource = true
20292075
)
20302076

2031-
liteRule.action, source, liteRule.port, liteRule.protocol = split[0], split[1], split[2], split[3]
2077+
liteRule.action, source, port, protocol = split[0], split[1], split[2], split[3]
20322078

20332079
if securityGroupIdRE.MatchString(source) {
20342080
liteRule.securityGroupId = source
@@ -2041,11 +2087,9 @@ func parseRule(str string) (liteRule VpcSecurityGroupLiteRule, err error) {
20412087
liteRule.cidrIp = source
20422088
}
20432089

2044-
switch liteRule.action {
2045-
default:
2046-
err = fmt.Errorf("invalid action %s, allow action is `ACCEPT` or `DROP`", liteRule.action)
2090+
if v := liteRule.action; v != "ACCEPT" && v != "DROP" {
2091+
err = fmt.Errorf("invalid action `%s`, available actions: `ACCEPT`, `DROP`", v)
20472092
return
2048-
case "ACCEPT", "DROP":
20492093
}
20502094

20512095
if net.ParseIP(liteRule.cidrIp) == nil && !isInstanceIdSource {
@@ -2055,26 +2099,33 @@ func parseRule(str string) (liteRule VpcSecurityGroupLiteRule, err error) {
20552099
}
20562100
}
20572101

2058-
if liteRule.port != "ALL" && !portRE.MatchString(liteRule.port) {
2102+
liteRule.port = port
2103+
if port != "ALL" && !portRE.MatchString(port) && !protocolTemplateRE.MatchString(protocol) {
20592104
err = fmt.Errorf("invalid port %s, allow port format is `ALL`, `53`, `80,443` or `80-90`", liteRule.port)
20602105
return
20612106
}
20622107

2063-
switch liteRule.protocol {
2064-
default:
2065-
err = fmt.Errorf("invalid protocol %s, allow protocol is `ALL`, `TCP`, `UDP` or `ICMP`", liteRule.protocol)
2066-
return
2067-
2068-
case "ALL", "ICMP":
2108+
liteRule.protocol = protocol
2109+
if protocolTemplateRE.MatchString(protocol) {
2110+
liteRule.port = ""
2111+
liteRule.protocol = ""
2112+
if protocolTemplateIdRE.MatchString(protocol) {
2113+
liteRule.protocolTemplateId = protocol
2114+
} else if protocolTemplateGroupIdRE.MatchString(protocol) {
2115+
liteRule.protocolTemplateGroupId = protocol
2116+
}
2117+
} else if protocol != "TCP" && protocol != "UDP" && protocol != "ALL" && protocol != "ICMP" {
2118+
err = fmt.Errorf("invalid protocol %s, allow protocol is `ALL`, `TCP`, `UDP`, `ICMP` or `ppm(g?)-xxxxxxxx`", liteRule.protocol)
2119+
} else if protocol == "ALL" || protocol == "ICMP" {
20692120
if liteRule.port != "ALL" {
2070-
err = fmt.Errorf("when protocol is %s, port must be ALL", liteRule.protocol)
2071-
return
2121+
err = fmt.Errorf("when protocol is %s, port must be ALL", protocol)
2122+
} else {
2123+
liteRule.port = ""
20722124
}
2125+
}
20732126

2074-
// when protocol is ALL or ICMP, port should be "" to avoid sdk error
2075-
liteRule.port = ""
2076-
2077-
case "TCP", "UDP":
2127+
if err != nil {
2128+
return
20782129
}
20792130

20802131
return

website/docs/r/security_group_lite_rule.html.markdown

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ resource "tencentcloud_security_group_lite_rule" "foo" {
3030
"ACCEPT#sg-7ixn3foj#80-90#TCP",
3131
"ACCEPT#ipm-epjq5kn0#80-90#TCP",
3232
"ACCEPT#ipmg-3loavam6#80-90#TCP",
33+
"ACCEPT#0.0.0.0/0##ppm-xxxxxxxx"
34+
"ACCEPT#0.0.0.0/0##ppmg-xxxxxxxx"
3335
]
3436
3537
egress = [
@@ -45,8 +47,8 @@ resource "tencentcloud_security_group_lite_rule" "foo" {
4547
The following arguments are supported:
4648

4749
* `security_group_id` - (Required, String, ForceNew) ID of the security group.
48-
* `egress` - (Optional, List: [`String`]) Egress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP` and `ALL`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.
49-
* `ingress` - (Optional, List: [`String`]) Ingress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP` and `ALL`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.
50+
* `egress` - (Optional, List: [`String`]) Egress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP`, `ALL` and `ppm(g?)-xxxxxxxx`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.
51+
* `ingress` - (Optional, List: [`String`]) Ingress rules set. A rule must match the following format: [action]#[source]#[port]#[protocol]. The available value of 'action' is `ACCEPT` and `DROP`. The 'source' can be an IP address network, segment, security group ID and Address Template ID. The 'port' valid format is `80`, `80,443`, `80-90` or `ALL`. The available value of 'protocol' is `TCP`, `UDP`, `ICMP`, `ALL` and `ppm(g?)-xxxxxxxx`. When 'protocol' is `ICMP` or `ALL`, the 'port' must be `ALL`.
5052

5153
## Attributes Reference
5254

0 commit comments

Comments
 (0)