Skip to content

Commit 2578217

Browse files
committed
d/aws_vpc_security_group_rule: New resource.
Acceptance test output: % make testacc TESTARGS='-run=TestAccVPCSecurityGroupRuleDataSource_' PKG=ec2 ACCTEST_PARALLELISM=3 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./internal/service/ec2/... -v -count 1 -parallel 3 -run=TestAccVPCSecurityGroupRuleDataSource_ -timeout 180m === RUN TestAccVPCSecurityGroupRuleDataSource_basic === PAUSE TestAccVPCSecurityGroupRuleDataSource_basic === RUN TestAccVPCSecurityGroupRuleDataSource_filter === PAUSE TestAccVPCSecurityGroupRuleDataSource_filter === CONT TestAccVPCSecurityGroupRuleDataSource_basic === CONT TestAccVPCSecurityGroupRuleDataSource_filter --- PASS: TestAccVPCSecurityGroupRuleDataSource_basic (23.71s) --- PASS: TestAccVPCSecurityGroupRuleDataSource_filter (23.93s) PASS ok github.com/hashicorp/terraform-provider-aws/internal/service/ec2 29.347s
1 parent 1e207cc commit 2578217

File tree

5 files changed

+346
-1
lines changed

5 files changed

+346
-1
lines changed

.changelog/29484.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ aws_vpc_security_group_egress_rule
99
```release-note:new-data-source
1010
aws_vpc_security_group_rules
1111
```
12+
13+
```release-note:new-data-source
14+
aws_vpc_security_group_rule
15+
```
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
package ec2
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/aws/aws-sdk-go/aws"
9+
"github.com/aws/aws-sdk-go/aws/arn"
10+
"github.com/aws/aws-sdk-go/service/ec2"
11+
"github.com/hashicorp/terraform-plugin-framework/datasource"
12+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
13+
"github.com/hashicorp/terraform-plugin-framework/types"
14+
"github.com/hashicorp/terraform-provider-aws/internal/flex"
15+
"github.com/hashicorp/terraform-provider-aws/internal/framework"
16+
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
17+
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
18+
)
19+
20+
func init() {
21+
_sp.registerFrameworkDataSourceFactory(newDataSourceSecurityGroupRule)
22+
}
23+
24+
func newDataSourceSecurityGroupRule(context.Context) (datasource.DataSourceWithConfigure, error) {
25+
return &dataSourceSecurityGroupRule{}, nil
26+
}
27+
28+
type dataSourceSecurityGroupRule struct {
29+
framework.DataSourceWithConfigure
30+
}
31+
32+
func (d *dataSourceSecurityGroupRule) Metadata(_ context.Context, request datasource.MetadataRequest, response *datasource.MetadataResponse) {
33+
response.TypeName = "aws_vpc_security_group_rule"
34+
}
35+
36+
func (d *dataSourceSecurityGroupRule) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
37+
resp.Schema = schema.Schema{
38+
Attributes: map[string]schema.Attribute{
39+
"arn": schema.StringAttribute{
40+
Computed: true,
41+
},
42+
"cidr_ipv4": schema.StringAttribute{
43+
Computed: true,
44+
},
45+
"cidr_ipv6": schema.StringAttribute{
46+
Computed: true,
47+
},
48+
"description": schema.StringAttribute{
49+
Computed: true,
50+
},
51+
"from_port": schema.Int64Attribute{
52+
Computed: true,
53+
},
54+
"id": framework.IDAttribute(),
55+
"ip_protocol": schema.StringAttribute{
56+
Computed: true,
57+
},
58+
"is_egress": schema.BoolAttribute{
59+
Computed: true,
60+
},
61+
"prefix_list_id": schema.StringAttribute{
62+
Computed: true,
63+
},
64+
"referenced_security_group_id": schema.StringAttribute{
65+
Computed: true,
66+
},
67+
"security_group_id": schema.StringAttribute{
68+
Computed: true,
69+
},
70+
"security_group_rule_id": schema.StringAttribute{
71+
Optional: true,
72+
Computed: true,
73+
},
74+
"tags": tftags.TagsAttributeComputedOnly(),
75+
"to_port": schema.Int64Attribute{
76+
Computed: true,
77+
},
78+
},
79+
Blocks: map[string]schema.Block{
80+
"filter": CustomFiltersBlock(),
81+
},
82+
}
83+
}
84+
85+
func (d *dataSourceSecurityGroupRule) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) {
86+
var data dataSourceSecurityGroupRuleData
87+
88+
response.Diagnostics.Append(request.Config.Get(ctx, &data)...)
89+
90+
if response.Diagnostics.HasError() {
91+
return
92+
}
93+
94+
conn := d.Meta().EC2Conn()
95+
ignoreTagsConfig := d.Meta().IgnoreTagsConfig
96+
97+
input := &ec2.DescribeSecurityGroupRulesInput{
98+
Filters: BuildCustomFilters(ctx, data.Filters),
99+
}
100+
101+
if !data.SecurityGroupRuleID.IsNull() {
102+
input.SecurityGroupRuleIds = []*string{flex.StringFromFramework(ctx, data.SecurityGroupRuleID)}
103+
}
104+
105+
output, err := FindSecurityGroupRule(ctx, conn, input)
106+
107+
if err != nil {
108+
response.Diagnostics.AddError("reading Security Group Rules", tfresource.SingularDataSourceFindError("Security Group Rule", err).Error())
109+
110+
return
111+
}
112+
113+
data.ID = flex.StringToFramework(ctx, output.SecurityGroupRuleId)
114+
data.ARN = d.arn(ctx, data.ID.ValueString())
115+
data.CIDRIPv4 = flex.StringToFramework(ctx, output.CidrIpv4)
116+
data.CIDRIPv6 = flex.StringToFramework(ctx, output.CidrIpv6)
117+
data.Description = flex.StringToFramework(ctx, output.Description)
118+
data.FromPort = flex.Int64ToFramework(ctx, output.FromPort)
119+
data.IPProtocol = flex.StringToFramework(ctx, output.IpProtocol)
120+
data.IsEgress = flex.BoolToFramework(ctx, output.IsEgress)
121+
data.PrefixListID = flex.StringToFramework(ctx, output.PrefixListId)
122+
data.ReferencedSecurityGroupID = d.flattenReferencedSecurityGroup(ctx, output.ReferencedGroupInfo)
123+
data.SecurityGroupID = flex.StringToFramework(ctx, output.GroupId)
124+
data.SecurityGroupRuleID = flex.StringToFramework(ctx, output.SecurityGroupRuleId)
125+
data.Tags = flex.FlattenFrameworkStringValueMapLegacy(ctx, KeyValueTags(output.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map())
126+
data.ToPort = flex.Int64ToFramework(ctx, output.ToPort)
127+
128+
response.Diagnostics.Append(response.State.Set(ctx, &data)...)
129+
}
130+
131+
func (d *dataSourceSecurityGroupRule) arn(_ context.Context, id string) types.String {
132+
// TODO Consider reusing resourceSecurityGroupRule.arn().
133+
arn := arn.ARN{
134+
Partition: d.Meta().Partition,
135+
Service: ec2.ServiceName,
136+
Region: d.Meta().Region,
137+
AccountID: d.Meta().AccountID,
138+
Resource: fmt.Sprintf("security-group-rule/%s", id),
139+
}.String()
140+
return types.StringValue(arn)
141+
}
142+
143+
func (d *dataSourceSecurityGroupRule) flattenReferencedSecurityGroup(ctx context.Context, apiObject *ec2.ReferencedSecurityGroup) types.String {
144+
// TODO Consider reusing resourceSecurityGroupRule.flattenReferencedSecurityGroup().
145+
if apiObject == nil {
146+
return types.StringNull()
147+
}
148+
149+
if apiObject.UserId == nil || aws.StringValue(apiObject.UserId) == d.Meta().AccountID {
150+
return flex.StringToFramework(ctx, apiObject.GroupId)
151+
}
152+
153+
// [UserID/]GroupID.
154+
return types.StringValue(strings.Join([]string{aws.StringValue(apiObject.UserId), aws.StringValue(apiObject.GroupId)}, "/"))
155+
}
156+
157+
type dataSourceSecurityGroupRuleData struct {
158+
ARN types.String `tfsdk:"arn"`
159+
CIDRIPv4 types.String `tfsdk:"cidr_ipv4"`
160+
CIDRIPv6 types.String `tfsdk:"cidr_ipv6"`
161+
Description types.String `tfsdk:"description"`
162+
Filters types.Set `tfsdk:"filter"`
163+
FromPort types.Int64 `tfsdk:"from_port"`
164+
ID types.String `tfsdk:"id"`
165+
IPProtocol types.String `tfsdk:"ip_protocol"`
166+
IsEgress types.Bool `tfsdk:"is_egress"`
167+
PrefixListID types.String `tfsdk:"prefix_list_id"`
168+
ReferencedSecurityGroupID types.String `tfsdk:"referenced_security_group_id"`
169+
SecurityGroupID types.String `tfsdk:"security_group_id"`
170+
SecurityGroupRuleID types.String `tfsdk:"security_group_rule_id"`
171+
Tags types.Map `tfsdk:"tags"`
172+
ToPort types.Int64 `tfsdk:"to_port"`
173+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package ec2_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/aws/aws-sdk-go/service/ec2"
8+
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
11+
)
12+
13+
func TestAccVPCSecurityGroupRuleDataSource_basic(t *testing.T) {
14+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
15+
dataSourceName := "data.aws_vpc_security_group_rule.test"
16+
resourceName := "aws_vpc_security_group_ingress_rule.test"
17+
18+
resource.ParallelTest(t, resource.TestCase{
19+
PreCheck: func() { acctest.PreCheck(t) },
20+
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
21+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testAccVPCSecurityGroupRuleDataSourceConfig_basic(rName),
25+
Check: resource.ComposeAggregateTestCheckFunc(
26+
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
27+
resource.TestCheckResourceAttrPair(dataSourceName, "cidr_ipv4", resourceName, "cidr_ipv4"),
28+
resource.TestCheckResourceAttrPair(dataSourceName, "cidr_ipv6", resourceName, "cidr_ipv6"),
29+
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
30+
resource.TestCheckResourceAttrPair(dataSourceName, "from_port", resourceName, "from_port"),
31+
resource.TestCheckResourceAttrPair(dataSourceName, "ip_protocol", resourceName, "ip_protocol"),
32+
resource.TestCheckResourceAttr(dataSourceName, "is_egress", "false"),
33+
resource.TestCheckResourceAttrPair(dataSourceName, "prefix_list_id", resourceName, "prefix_list_id"),
34+
resource.TestCheckResourceAttrPair(dataSourceName, "referenced_security_group_id", resourceName, "referenced_security_group_id"),
35+
resource.TestCheckResourceAttrPair(dataSourceName, "security_group_id", resourceName, "security_group_id"),
36+
resource.TestCheckResourceAttrPair(dataSourceName, "security_group_rule_id", resourceName, "security_group_rule_id"),
37+
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
38+
resource.TestCheckResourceAttrPair(dataSourceName, "to_port", resourceName, "to_port"),
39+
),
40+
},
41+
},
42+
})
43+
}
44+
45+
func TestAccVPCSecurityGroupRuleDataSource_filter(t *testing.T) {
46+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
47+
dataSourceName := "data.aws_vpc_security_group_rule.test"
48+
resourceName := "aws_vpc_security_group_egress_rule.test"
49+
50+
resource.ParallelTest(t, resource.TestCase{
51+
PreCheck: func() { acctest.PreCheck(t) },
52+
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
53+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
54+
Steps: []resource.TestStep{
55+
{
56+
Config: testAccVPCSecurityGroupRuleDataSourceConfig_filter(rName),
57+
Check: resource.ComposeAggregateTestCheckFunc(
58+
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
59+
resource.TestCheckResourceAttrPair(dataSourceName, "cidr_ipv4", resourceName, "cidr_ipv4"),
60+
resource.TestCheckResourceAttrPair(dataSourceName, "cidr_ipv6", resourceName, "cidr_ipv6"),
61+
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
62+
resource.TestCheckResourceAttrPair(dataSourceName, "from_port", resourceName, "from_port"),
63+
resource.TestCheckResourceAttrPair(dataSourceName, "ip_protocol", resourceName, "ip_protocol"),
64+
resource.TestCheckResourceAttr(dataSourceName, "is_egress", "true"),
65+
resource.TestCheckResourceAttrPair(dataSourceName, "prefix_list_id", resourceName, "prefix_list_id"),
66+
resource.TestCheckResourceAttrPair(dataSourceName, "referenced_security_group_id", resourceName, "referenced_security_group_id"),
67+
resource.TestCheckResourceAttrPair(dataSourceName, "security_group_id", resourceName, "security_group_id"),
68+
resource.TestCheckResourceAttrPair(dataSourceName, "security_group_rule_id", resourceName, "security_group_rule_id"),
69+
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
70+
resource.TestCheckResourceAttrPair(dataSourceName, "to_port", resourceName, "to_port"),
71+
),
72+
},
73+
},
74+
})
75+
}
76+
77+
func testAccVPCSecurityGroupRuleDataSourceConfig_basic(rName string) string {
78+
return acctest.ConfigCompose(testAccVPCSecurityGroupRuleConfig_base(rName), `
79+
resource "aws_vpc_security_group_ingress_rule" "test" {
80+
security_group_id = aws_security_group.test.id
81+
82+
cidr_ipv4 = "10.0.0.0/8"
83+
from_port = 80
84+
ip_protocol = "tcp"
85+
to_port = 8080
86+
}
87+
88+
data "aws_vpc_security_group_rule" "test" {
89+
security_group_rule_id = aws_vpc_security_group_ingress_rule.test.id
90+
}
91+
`)
92+
}
93+
94+
func testAccVPCSecurityGroupRuleDataSourceConfig_filter(rName string) string {
95+
return acctest.ConfigCompose(testAccVPCSecurityGroupRuleConfig_base(rName), fmt.Sprintf(`
96+
resource "aws_vpc_security_group_egress_rule" "test" {
97+
security_group_id = aws_security_group.test.id
98+
99+
cidr_ipv6 = "2001:db8:85a3::/64"
100+
from_port = 80
101+
ip_protocol = "tcp"
102+
to_port = 8080
103+
104+
tags = {
105+
Name = %[1]q
106+
}
107+
}
108+
109+
data "aws_vpc_security_group_rule" "test" {
110+
filter {
111+
name = "security-group-rule-id"
112+
values = [aws_vpc_security_group_egress_rule.test.id]
113+
}
114+
}
115+
`, rName))
116+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
subcategory: "VPC (Virtual Private Cloud)"
3+
layout: "aws"
4+
page_title: "AWS: aws_vpc_security_group_rule"
5+
description: |-
6+
Provides details about a specific security group rule
7+
---
8+
9+
# Data Source: aws_vpc_security_group_rule
10+
11+
`aws_vpc_security_group_rule` provides details about a specific security group rule.
12+
13+
## Example Usage
14+
15+
```terraform
16+
data "aws_vpc_security_group_rule" "example" {
17+
security_group_rule_id = var.security_group_rule_id
18+
}
19+
```
20+
21+
## Argument Reference
22+
23+
The arguments of this data source act as filters for querying the available
24+
security group rules. The given filters must match exactly one security group rule
25+
whose data will be exported as attributes.
26+
27+
* `security_group_rule_id` - (Optional) ID of the security group rule to select.
28+
* `filter` - (Optional) Configuration block(s) for filtering. Detailed below.
29+
30+
### filter Configuration Block
31+
32+
The following arguments are supported by the `filter` configuration block:
33+
34+
* `name` - (Required) Name of the filter field. Valid values can be found in the EC2 [`DescribeSecurityGroupRules`](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroupRules.html) API Reference.
35+
* `values` - (Required) Set of values that are accepted for the given filter field. Results will be selected if any given value matches.
36+
37+
## Attributes Reference
38+
39+
In addition to all arguments above, the following attributes are exported:
40+
41+
* `arn` - The Amazon Resource Name (ARN) of the security group rule.
42+
* `cidr_ipv4` - The destination IPv4 CIDR range.
43+
* `cidr_ipv6` - The destination IPv6 CIDR range.
44+
* `description` - The security group rule description.
45+
* `from_port` - The start of port range for the TCP and UDP protocols, or an ICMP/ICMPv6 type.
46+
* `is_egress` - Indicates whether the security group rule is an outbound rule.
47+
* `ip_protocol` - The IP protocol name or number. Use `-1` to specify all protocols.
48+
* `prefix_list_id` - The ID of the destination prefix list.
49+
* `referenced_security_group_id` - The destination security group that is referenced in the rule.
50+
* `security_group_id` - The ID of the security group.
51+
* `tags` - A map of tags assigned to the resource.
52+
* `to_port` - (Optional) The end of port range for the TCP and UDP protocols, or an ICMP/ICMPv6 code.

website/docs/d/vpc_security_group_rules.html.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ subcategory: "VPC (Virtual Private Cloud)"
33
layout: "aws"
44
page_title: "AWS: aws_vpc_security_group_rules"
55
description: |-
6-
Get information about a set of security group ruleds.
6+
Get information about a set of security group rules.
77
---
88

99
# Data Source: aws_vpc_security_group_rules

0 commit comments

Comments
 (0)