diff --git a/.changelog/29968.txt b/.changelog/29968.txt new file mode 100644 index 00000000000..41df44b0414 --- /dev/null +++ b/.changelog/29968.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_emr_block_public_access_configuration +``` diff --git a/internal/service/emr/block_public_access_configuration.go b/internal/service/emr/block_public_access_configuration.go new file mode 100644 index 00000000000..173b8625b62 --- /dev/null +++ b/internal/service/emr/block_public_access_configuration.go @@ -0,0 +1,204 @@ +package emr + +import ( + "context" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/emr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @SDKResource("aws_emr_block_public_access_configuration") +func ResourceBlockPublicAccessConfiguration() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceBlockPublicAccessConfigurationCreate, + ReadWithoutTimeout: resourceBlockPublicAccessConfigurationRead, + DeleteWithoutTimeout: resourceBlockPublicAccessConfigurationDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "block_public_security_group_rules": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + }, + "permitted_public_security_group_rule_range": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "min_range": { + Type: schema.TypeInt, + Required: true, + ValidateDiagFunc: validation.ToDiagFunc(validation.IsPortNumber), + }, + "max_range": { + Type: schema.TypeInt, + Required: true, + ValidateDiagFunc: validation.ToDiagFunc(validation.IsPortNumber), + }, + }, + }, + }, + }, + } +} + +const ( + ResNameBlockPublicAccessConfiguration = "Block Public Access Configuration" + dummyIDBlockPublicAccessConfiguration = "emr-block-public-access-configuration" + defaultPermittedPublicSecurityGroupRulePort = 22 +) + +func resourceBlockPublicAccessConfigurationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).EMRConn() + + blockPublicAccessConfiguration := &emr.BlockPublicAccessConfiguration{} + + blockPublicSecurityGroupRules := d.Get("block_public_security_group_rules") + blockPublicAccessConfiguration.BlockPublicSecurityGroupRules = aws.Bool(blockPublicSecurityGroupRules.(bool)) + if v, ok := d.GetOk("permitted_public_security_group_rule_range"); ok { + blockPublicAccessConfiguration.PermittedPublicSecurityGroupRuleRanges = expandPermittedPublicSecurityGroupRuleRanges(v.([]interface{})) + } + + in := &emr.PutBlockPublicAccessConfigurationInput{ + BlockPublicAccessConfiguration: blockPublicAccessConfiguration, + } + + _, err := conn.PutBlockPublicAccessConfigurationWithContext(ctx, in) + if err != nil { + return create.DiagError(names.EMR, create.ErrActionCreating, ResNameBlockPublicAccessConfiguration, d.Id(), err) + } + d.SetId(dummyIDBlockPublicAccessConfiguration) + + return resourceBlockPublicAccessConfigurationRead(ctx, d, meta) +} + +func resourceBlockPublicAccessConfigurationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).EMRConn() + + out, err := FindBlockPublicAccessConfiguration(ctx, conn) + + if err != nil { + return create.DiagError(names.EMR, create.ErrActionReading, ResNameBlockPublicAccessConfiguration, d.Id(), err) + } + + d.Set("block_public_security_group_rules", out.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules) + if err := d.Set("permitted_public_security_group_rule_range", flattenPermittedPublicSecurityGroupRuleRanges(out.BlockPublicAccessConfiguration.PermittedPublicSecurityGroupRuleRanges)); err != nil { + return create.DiagError(names.EMR, create.ErrActionSetting, ResNameBlockPublicAccessConfiguration, d.Id(), err) + } + + return nil +} + +func resourceBlockPublicAccessConfigurationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).EMRConn() + + log.Print("[INFO] Restoring EMR Block Public Access Configuration to default settings") + + blockPublicAccessConfiguration := findDefaultBlockPublicAccessConfiguration() + in := &emr.PutBlockPublicAccessConfigurationInput{ + BlockPublicAccessConfiguration: blockPublicAccessConfiguration, + } + + _, err := conn.PutBlockPublicAccessConfigurationWithContext(ctx, in) + if err != nil { + return create.DiagError(names.EMR, create.ErrActionDeleting, ResNameBlockPublicAccessConfiguration, d.Id(), err) + } + + return nil +} + +func findDefaultBlockPublicAccessConfiguration() *emr.BlockPublicAccessConfiguration { + defaultPort := int64(defaultPermittedPublicSecurityGroupRulePort) + defaultPortPointer := &defaultPort + portRange := &emr.PortRange{MinRange: defaultPortPointer, MaxRange: defaultPortPointer} + permittedPublicSecurityGroupRuleRanges := []*emr.PortRange{portRange} + blockPublicAccessConfiguration := &emr.BlockPublicAccessConfiguration{ + BlockPublicSecurityGroupRules: aws.Bool(true), + PermittedPublicSecurityGroupRuleRanges: permittedPublicSecurityGroupRuleRanges, + } + return blockPublicAccessConfiguration +} + +func flattenPermittedPublicSecurityGroupRuleRange(apiObject *emr.PortRange) map[string]interface{} { + if apiObject == nil { + return nil + } + + m := map[string]interface{}{} + + if v := apiObject.MinRange; v != nil { + m["min_range"] = aws.Int64Value(v) + } + + if v := apiObject.MaxRange; v != nil { + m["max_range"] = aws.Int64Value(v) + } + + return m +} + +func flattenPermittedPublicSecurityGroupRuleRanges(apiObjects []*emr.PortRange) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var l []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + l = append(l, flattenPermittedPublicSecurityGroupRuleRange(apiObject)) + } + + return l +} + +func expandPermittedPublicSecurityGroupRuleRange(tfMap map[string]interface{}) *emr.PortRange { + a := &emr.PortRange{} + + a.MinRange = aws.Int64(int64(tfMap["min_range"].(int))) + + a.MaxRange = aws.Int64(int64(tfMap["max_range"].(int))) + + return a +} + +func expandPermittedPublicSecurityGroupRuleRanges(tfList []interface{}) []*emr.PortRange { + if len(tfList) == 0 { + return nil + } + + var s []*emr.PortRange + + for _, r := range tfList { + m, ok := r.(map[string]interface{}) + + if !ok { + continue + } + + a := expandPermittedPublicSecurityGroupRuleRange(m) + + if a == nil { + continue + } + + s = append(s, a) + } + + return s +} diff --git a/internal/service/emr/block_public_access_configuration_test.go b/internal/service/emr/block_public_access_configuration_test.go new file mode 100644 index 00000000000..db24233b022 --- /dev/null +++ b/internal/service/emr/block_public_access_configuration_test.go @@ -0,0 +1,374 @@ +package emr_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/emr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfemr "github.com/hashicorp/terraform-provider-aws/internal/service/emr" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccEMRBlockPublicAccessConfiguration_basic(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_emr_block_public_access_configuration.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, emr.EndpointsID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, emr.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckBlockPublicAccessConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccBlockPublicAccessConfigurationConfig_basic(true), + Check: resource.ComposeTestCheckFunc( + testAccCheckBlockPublicAccessConfigurationAttributes_enabledOnly(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "block_public_security_group_rules", "true"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.#", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, + { + Config: testAccBlockPublicAccessConfigurationConfig_basic(false), + Check: resource.ComposeTestCheckFunc( + testAccCheckBlockPublicAccessConfigurationAttributes_disabled(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "block_public_security_group_rules", "false"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.#", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, + }, + }) +} + +func TestAccEMRBlockPublicAccessConfiguration_disappears(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_emr_block_public_access_configuration.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, emr.EndpointsID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, emr.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckBlockPublicAccessConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccBlockPublicAccessConfigurationConfig_basic(true), + Check: resource.ComposeTestCheckFunc( + testAccCheckBlockPublicAccessConfigurationAttributes_enabledOnly(ctx, resourceName), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfemr.ResourceBlockPublicAccessConfiguration(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, + }, + }) +} + +func TestAccEMRBlockPublicAccessConfiguration_default(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_emr_block_public_access_configuration.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, emr.EndpointsID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, emr.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckBlockPublicAccessConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: blockPublicAccessConfigurationConfig_defaultString, + Check: resource.ComposeTestCheckFunc( + testAccCheckBlockPublicAccessConfigurationAttributes_default(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "block_public_security_group_rules", "true"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.0.min_range", "22"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.0.max_range", "22"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, + }, + }) +} + +func TestAccEMRBlockPublicAccessConfiguration_enabledMultiRange(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_emr_block_public_access_configuration.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, emr.EndpointsID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, emr.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckBlockPublicAccessConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: blockPublicAccessConfigurationConfig_enabledMultiRangeString, + Check: resource.ComposeTestCheckFunc( + testAccCheckBlockPublicAccessConfigurationAttributes_enabledMultiRange(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "block_public_security_group_rules", "true"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.#", "2"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.0.min_range", "22"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.0.max_range", "22"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.1.min_range", "100"), + resource.TestCheckResourceAttr(resourceName, "permitted_public_security_group_rule_range.1.max_range", "101"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, + }, + }) +} + +func testAccCheckBlockPublicAccessConfigurationDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).EMRConn() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_emr_block_public_access_configuration" { + continue + } + + resp, err := tfemr.FindBlockPublicAccessConfiguration(ctx, conn) + + if err != nil { + return err + } + + blockPublicSecurityGroupRules := resp.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules + permittedPublicSecurityGroupRuleRanges := resp.BlockPublicAccessConfiguration.PermittedPublicSecurityGroupRuleRanges + + if *blockPublicSecurityGroupRules != true { + return fmt.Errorf("Block Public Security Group Rules is not enabled") + } + + if length := len(permittedPublicSecurityGroupRuleRanges); length != 1 { + return fmt.Errorf("The incorrect number (%v) of permitted public security group rule ranges exist, should be 1 by default", length) + } + if p := permittedPublicSecurityGroupRuleRanges; !((*p[0].MinRange == 22 && *p[0].MaxRange == 22) || (*p[1].MinRange == 22 || *p[1].MaxRange == 22)) { + return fmt.Errorf("Port 22 is not open as a permitted public security group rule") + } + } + + return nil + } +} + +func testAccCheckBlockPublicAccessConfigurationAttributes_enabledOnly(ctx context.Context, name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, name, errors.New("not found")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).EMRConn() + resp, err := tfemr.FindBlockPublicAccessConfiguration(ctx, conn) + + if err != nil { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, rs.Primary.ID, err) + } + + blockPublicSecurityGroupRules := resp.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules + permittedPublicSecurityGroupRuleRanges := resp.BlockPublicAccessConfiguration.PermittedPublicSecurityGroupRuleRanges + + if *blockPublicSecurityGroupRules != true { + return fmt.Errorf("Block Public Security Group Rules is not enabled") + } + + if length := len(permittedPublicSecurityGroupRuleRanges); length != 0 { + return fmt.Errorf("The incorrect number (%v) of permitted public security group rule ranges have been created, should be 0", length) + } + + return nil + } +} + +func testAccCheckBlockPublicAccessConfigurationAttributes_default(ctx context.Context, name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).EMRConn() + + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, name, errors.New("not found")) + } + + resp, err := tfemr.FindBlockPublicAccessConfiguration(ctx, conn) + + if err != nil { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, rs.Primary.ID, err) + } + + blockPublicSecurityGroupRules := resp.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules + permittedPublicSecurityGroupRuleRanges := resp.BlockPublicAccessConfiguration.PermittedPublicSecurityGroupRuleRanges + + if *blockPublicSecurityGroupRules != true { + return fmt.Errorf("Block Public Security Group Rules is not enabled") + } + + if length := len(permittedPublicSecurityGroupRuleRanges); length != 1 { + return fmt.Errorf("The incorrect number (%v) of permitted public security group rule ranges exist, should be 1 by default", length) + } + if p := permittedPublicSecurityGroupRuleRanges; !((*p[0].MinRange == 22 && *p[0].MaxRange == 22) || (*p[1].MinRange == 22 || *p[1].MaxRange == 22)) { + return fmt.Errorf("Port 22 is not open as a permitted public security group rule") + } + + return nil + } +} + +func testAccCheckBlockPublicAccessConfigurationAttributes_enabledMultiRange(ctx context.Context, name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, name, errors.New("not found")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).EMRConn() + resp, err := tfemr.FindBlockPublicAccessConfiguration(ctx, conn) + + if err != nil { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, rs.Primary.ID, err) + } + + blockPublicSecurityGroupRules := resp.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules + permittedPublicSecurityGroupRuleRanges := resp.BlockPublicAccessConfiguration.PermittedPublicSecurityGroupRuleRanges + + if *blockPublicSecurityGroupRules != true { + return fmt.Errorf("Block Public Security Group Rules is not enabled") + } + + if length := len(permittedPublicSecurityGroupRuleRanges); length != 2 { + return fmt.Errorf("The incorrect number (%v) of permitted public security group rule ranges have been created, should be 2", length) + } + if p := permittedPublicSecurityGroupRuleRanges; !((*p[0].MinRange == 22 && *p[0].MaxRange == 22) || (*p[1].MinRange == 22 || *p[1].MaxRange == 22)) { + return fmt.Errorf("Port 22 has not been opened as a permitted_public_security_group_rule") + } + if p := permittedPublicSecurityGroupRuleRanges; !((*p[0].MinRange == 100 && *p[0].MaxRange == 101) || (*p[1].MinRange == 100 || *p[1].MaxRange == 101)) { + return fmt.Errorf("Ports 100-101 have not been opened as a permitted_public_security_group_rule") + } + + return nil + } +} + +func testAccCheckBlockPublicAccessConfigurationAttributes_disabled(ctx context.Context, name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, name, errors.New("not found")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).EMRConn() + resp, err := tfemr.FindBlockPublicAccessConfiguration(ctx, conn) + + if err != nil { + return create.Error(names.EMR, create.ErrActionCheckingExistence, tfemr.ResNameBlockPublicAccessConfiguration, rs.Primary.ID, err) + } + + blockPublicSecurityGroupRules := resp.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules + permittedPublicSecurityGroupRuleRanges := resp.BlockPublicAccessConfiguration.PermittedPublicSecurityGroupRuleRanges + + if *blockPublicSecurityGroupRules != false { + return fmt.Errorf("Block Public Security Group Rules is not disabled") + } + + if length := len(permittedPublicSecurityGroupRuleRanges); length != 0 { + return fmt.Errorf("The incorrect number (%v) of permitted public security group rule ranges have been created, should be 0", length) + } + return nil + } +} + +func testAccPreCheck(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).EMRConn() + + input := &emr.GetBlockPublicAccessConfigurationInput{} + _, err := conn.GetBlockPublicAccessConfigurationWithContext(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccBlockPublicAccessConfigurationConfig_basic(enabled bool) string { + return fmt.Sprintf(` +resource "aws_emr_block_public_access_configuration" "test" { + block_public_security_group_rules = %[1]t +} +`, enabled) +} + +const blockPublicAccessConfigurationConfig_defaultString = ` +resource "aws_emr_block_public_access_configuration" "test" { + block_public_security_group_rules = true + + permitted_public_security_group_rule_range { + min_range = 22 + max_range = 22 + } +} +` + +const blockPublicAccessConfigurationConfig_enabledMultiRangeString = ` +resource "aws_emr_block_public_access_configuration" "test" { + block_public_security_group_rules = true + + permitted_public_security_group_rule_range { + min_range = 22 + max_range = 22 + } + + permitted_public_security_group_rule_range { + min_range = 100 + max_range = 101 + } +} +` diff --git a/internal/service/emr/find.go b/internal/service/emr/find.go index 1fccb3c85d9..d5300ebea7a 100644 --- a/internal/service/emr/find.go +++ b/internal/service/emr/find.go @@ -116,3 +116,17 @@ func FindStudioSessionMappingByID(ctx context.Context, conn *emr.EMR, id string) return output.SessionMapping, nil } + +func FindBlockPublicAccessConfiguration(ctx context.Context, conn *emr.EMR) (*emr.GetBlockPublicAccessConfigurationOutput, error) { + input := &emr.GetBlockPublicAccessConfigurationInput{} + output, err := conn.GetBlockPublicAccessConfigurationWithContext(ctx, input) + if err != nil { + return nil, err + } + + if output == nil || output.BlockPublicAccessConfiguration == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} diff --git a/internal/service/emr/service_package_gen.go b/internal/service/emr/service_package_gen.go index 5a4e0782223..bea3f7faa11 100644 --- a/internal/service/emr/service_package_gen.go +++ b/internal/service/emr/service_package_gen.go @@ -30,6 +30,10 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ + { + Factory: ResourceBlockPublicAccessConfiguration, + TypeName: "aws_emr_block_public_access_configuration", + }, { Factory: ResourceCluster, TypeName: "aws_emr_cluster", diff --git a/website/docs/r/emr_block_public_access_configuration.html.markdown b/website/docs/r/emr_block_public_access_configuration.html.markdown new file mode 100644 index 00000000000..5702341b2b5 --- /dev/null +++ b/website/docs/r/emr_block_public_access_configuration.html.markdown @@ -0,0 +1,97 @@ +--- +subcategory: "EMR" +layout: "aws" +page_title: "AWS: aws_emr_block_public_access_configuration" +description: |- + Terraform resource for managing an AWS EMR Block Public Access Configuration. +--- + +# Resource: aws_emr_block_public_access_configuration + +Terraform resource for managing an AWS EMR block public access configuration. This region level security configuration restricts the launch of EMR clusters that have associated security groups permitting public access on unspecified ports. See the [EMR Block Public Access Configuration](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html) documentation for further information. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_emr_block_public_access_configuration" "example" { + block_public_security_group_rules = true +} +``` + +### Default Configuration + +By default, each AWS region is equipped with a block public access configuration that prevents EMR clusters from being launched if they have security group rules permitting public access on any port except for port 22. The default configuration can be managed using this Terraform resource. + +```terraform +resource "aws_emr_block_public_access_configuration" "example" { + block_public_security_group_rules = true + + permitted_public_security_group_rule_range { + min_range = 22 + max_range = 22 + } +} +``` + +~> **NOTE:** If an `aws_emr_block_public_access_configuration` Terraform resource is destroyed, the configuration will reset to this default configuration. + +### Multiple Permitted Public Security Group Rule Ranges + +The resource permits specification of multiple `permitted_public_security_group_rule_range` blocks. + +```terraform +resource "aws_emr_block_public_access_configuration" "example" { + block_public_security_group_rules = true + + permitted_public_security_group_rule_range { + min_range = 22 + max_range = 22 + } + + permitted_public_security_group_rule_range { + min_range = 100 + max_range = 101 + } +} +``` + +### Disabling Block Public Access + +To permit EMR clusters to be launched in the configured region regardless of associated security group rules, the Block Public Access feature can be disabled using this Terraform resource. + +```terraform +resource "aws_emr_block_public_access_configuration" "example" { + block_public_security_group_rules = false +} +``` + +## Argument Reference + +The following arguments are required: + +* `block_public_security_group_rules` - (Required) Enable or disable EMR Block Public Access. + +The following arguments are optional: + +* `permitted_public_security_group_rule_range` - (Optional) Configuration block for defining permitted public security group rule port ranges. Can be defined multiple times per resource. Only valid if `block_public_security_group_rules` is set to `true`. + +### `permitted_public_security_group_rule_range` + +This block is used to define a range of TCP ports that should form exceptions to the Block Public Access Configuration. If an attempt is made to launch an EMR cluster in the configured region and account, with `block_public_security_group_rules = true`, the EMR cluster will be permitted to launch even if there are security group rules permitting public access to ports in this range. + +* `min_range` - (Required) The first port in the range of TCP ports. +* `max_range` - (Required) The final port in the range of TCP ports. + +## Attributes Reference + +No additional attributes are exported. + +## Import + +The current EMR Block Public Access Configuration can be imported, e.g., + +``` +$ terraform import aws_emr_block_public_access_configuration.example current +```