From 4fae268fd63a00a09be2eeace197781a57f41ce6 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:15:29 -0500 Subject: [PATCH 01/68] [WIP] Schema, CRD functions --- .../tls_inspection_configuration.go | 956 ++++++++++++++++++ .../tls_inspection_configuration_test.go | 332 ++++++ 2 files changed, 1288 insertions(+) create mode 100644 internal/service/networkfirewall/tls_inspection_configuration.go create mode 100644 internal/service/networkfirewall/tls_inspection_configuration_test.go diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go new file mode 100644 index 00000000000..e3f66b021fe --- /dev/null +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -0,0 +1,956 @@ +package networkfirewall + +import ( + // TIP: ==== IMPORTS ==== + // This is a common set of imports but not customized to your code since + // your code hasn't been written yet. Make sure you, your IDE, or + // goimports -w fixes these imports. + // + // The provider linter wants your imports to be in two groups: first, + // standard library (i.e., "fmt" or "strings"), second, everything else. + // + // Also, AWS Go SDK v2 may handle nested structures differently than v1, + // using the services/networkfirewall/types package. If so, you'll + // need to import types and reference the nested types, e.g., as + // awstypes.. + "context" + "errors" + "time" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) +// TIP: ==== FILE STRUCTURE ==== +// All resources should follow this basic outline. Improve this resource's +// maintainability by sticking to it. +// +// 1. Package declaration +// 2. Imports +// 3. Main resource struct with schema method +// 4. Create, read, update, delete methods (in that order) +// 5. Other functions (flatteners, expanders, waiters, finders, etc.) + +// Function annotations are used for resource registration to the Provider. DO NOT EDIT. +// @FrameworkResource(name="TLS Inspection Configuration") +func newResourceTLSInspectionConfiguration(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceTLSInspectionConfiguration{} + + // TIP: ==== CONFIGURABLE TIMEOUTS ==== + // Users can configure timeout lengths but you need to use the times they + // provide. Access the timeout they configure (or the defaults) using, + // e.g., r.CreateTimeout(ctx, plan.Timeouts) (see below). The times here are + // the defaults if they don't configure timeouts. + r.SetDefaultCreateTimeout(30 * time.Minute) + r.SetDefaultUpdateTimeout(30 * time.Minute) + r.SetDefaultDeleteTimeout(30 * time.Minute) + + return r, nil +} + +const ( + ResNameTLSInspectionConfiguration = "TLS Inspection Configuration" +) + +type resourceTLSInspectionConfiguration struct { + framework.ResourceWithConfigure + framework.WithTimeouts +} + +func (r *resourceTLSInspectionConfiguration) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_networkfirewall_tls_inspection_configuration" +} + +// TIP: ==== SCHEMA ==== +// In the schema, add each of the attributes in snake case (e.g., +// delete_automated_backups). +// +// Formatting rules: +// * Alphabetize attributes to make them easier to find. +// * Do not add a blank line between attributes. +// +// Attribute basics: +// * If a user can provide a value ("configure a value") for an +// attribute (e.g., instances = 5), we call the attribute an +// "argument." +// * You change the way users interact with attributes using: +// - Required +// - Optional +// - Computed +// * There are only four valid combinations: +// +// 1. Required only - the user must provide a value +// Required: true, +// +// 2. Optional only - the user can configure or omit a value; do not +// use Default or DefaultFunc +// Optional: true, +// +// 3. Computed only - the provider can provide a value but the user +// cannot, i.e., read-only +// Computed: true, +// +// 4. Optional AND Computed - the provider or user can provide a value; +// use this combination if you are using Default +// Optional: true, +// Computed: true, +// +// You will typically find arguments in the input struct +// (e.g., CreateDBInstanceInput) for the create operation. Sometimes +// they are only in the input struct (e.g., ModifyDBInstanceInput) for +// the modify operation. +// +// For more about schema options, visit +// https://developer.hashicorp.com/terraform/plugin/framework/handling-data/schemas?page=schemas +func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "arn": framework.ARNAttributeComputedOnly(), + "description": schema.StringAttribute{ + Optional: true, + }, + "id": framework.IDAttribute(), + // Map name to TLSInspectionConfigurationName + "name": schema.StringAttribute{ + Required: true, + // TIP: ==== PLAN MODIFIERS ==== + // Plan modifiers were introduced with Plugin-Framework to provide a mechanism + // for adjusting planned changes prior to apply. The planmodifier subpackage + // provides built-in modifiers for many common use cases such as + // requiring replacement on a value change ("ForceNew: true" in Plugin-SDK + // resources). + // + // See more: + // https://developer.hashicorp.com/terraform/plugin/framework/resources/plan-modification + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "last_modified_time": schema.StringAttribute{ + Computed: true, + }, + "number_of_associations": schema.Int64Attribute{ + Computed: true, + }, + "status": schema.StringAttribute{ + Computed: true, + }, + "update_token": schema.StringAttribute{ + Computed: true, + }, + }, + Blocks: map[string]schema.Block{ + "encryption_configuration": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "key_id": schema.StringAttribute{ + Optional: true, + }, + "type": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + "tls_inspection_configuration": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Blocks: map[string]schema.Block{ + "server_certificate_configurations": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "certificate_authority_arn": schema.StringAttribute{ + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "check_certificate_revocation_status": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "revoked_status_action": schema.StringAttribute{ + Optional: true, + }, + "unknown_status_action": schema.StringAttribute{ + Optional: true, + }, + }, + }, + }, + "server_certificates": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "resource_arn": schema.StringAttribute{ + Optional: true, + // TODO: Add string validation with regex + }, + }, + }, + }, + "scopes": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "protocols": schema.ListAttribute{ + ElementType: types.StringType, + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "destination_ports": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "from_port": schema.Int64Attribute{ + Required: true, + }, + "to_port": schema.Int64Attribute{ + Required: true, + }, + }, + }, + }, + "destinations": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "address_definition": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + "source_ports": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "from_port": schema.Int64Attribute{ + Required: true, + }, + "to_port": schema.Int64Attribute{ + Required: true, + }, + }, + }, + }, + "sources": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "address_definition": schema.StringAttribute{ + Required: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + // "complex_argument": schema.ListNestedBlock{ + // // TIP: ==== LIST VALIDATORS ==== + // // List and set validators take the place of MaxItems and MinItems in + // // Plugin-Framework based resources. Use listvalidator.SizeAtLeast(1) to + // // make a nested object required. Similar to Plugin-SDK, complex objects + // // can be represented as lists or sets with listvalidator.SizeAtMost(1). + // // + // // For a complete mapping of Plugin-SDK to Plugin-Framework schema fields, + // // see: + // // https://developer.hashicorp.com/terraform/plugin/framework/migrating/attributes-blocks/blocks + // Validators: []validator.List{ + // listvalidator.SizeAtMost(1), + // }, + // NestedObject: schema.NestedBlockObject{ + // Attributes: map[string]schema.Attribute{ + // "nested_required": schema.StringAttribute{ + // Required: true, + // }, + // "nested_computed": schema.StringAttribute{ + // Computed: true, + // PlanModifiers: []planmodifier.String{ + // stringplanmodifier.UseStateForUnknown(), + // }, + // }, + // }, + // }, + // }, + "timeouts": timeouts.Block(ctx, timeouts.Opts{ + Create: true, + Update: true, + Delete: true, + }), + }, + } +} + +func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + // TIP: ==== RESOURCE CREATE ==== + // Generally, the Create function should do the following things. Make + // sure there is a good reason if you don't do one of these. + // + // 1. Get a client connection to the relevant service + // 2. Fetch the plan + // 3. Populate a create input structure + // 4. Call the AWS create/put function + // 5. Using the output from the create function, set the minimum arguments + // and attributes for the Read function to work, as well as any computed + // only attributes. + // 6. Use a waiter to wait for create to complete + // 7. Save the request plan to response state + + // TIP: -- 1. Get a client connection to the relevant service + conn := r.Meta().NetworkFirewallConn(ctx) + + // TIP: -- 2. Fetch the plan + var plan resourceTLSInspectionConfigurationData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + // TIP: -- 3. Populate a create input structure + in := &networkfirewall.CreateTLSInspectionConfigurationInput{ + // NOTE: Name is mandatory + TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), + } + + if !plan.Description.IsNull() { + // NOTE: Description is optional + in.Description = aws.String(plan.Description.ValueString()) + } + + // Complex arguments + if !plan.TLSInspectionConfiguration.IsNull() { + // TIP: Use an expander to assign a complex argument. The elements must be + // deserialized into the appropriate struct before being passed to the expander. + var tfList []complexArgumentData + resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) + if resp.Diagnostics.HasError() { + return + } + + in.TLSInspectionConfiguration = expandComplexArgument(tfList) + } + + if !plan.EncryptionConfiguration.IsNull() { + // TIP: Use an expander to assign a complex argument. The elements must be + // deserialized into the appropriate struct before being passed to the expander. + var tfList []complexArgumentData + resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) + if resp.Diagnostics.HasError() { + return + } + + in.TLSInspectionConfiguration = expandComplexArgument(tfList) + } + + // TIP: -- 4. Call the AWS create function + out, err := conn.CreateTLSInspectionConfiguration(in) + if err != nil { + // TIP: Since ID has not been set yet, you cannot use plan.ID.String() + // in error messages at this point. + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), err), + err.Error(), + ) + return + } + if out == nil || out.TLSInspectionConfigurationResponse == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), nil), + errors.New("empty output").Error(), + ) + return + } + + // TIP: -- 5. Using the output from the create function, set the minimum attributes + // Output consists only of TLSInspectionConfigurationResponse + plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) + plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) + + // TIP: -- 6. Use a waiter to wait for create to complete + createTimeout := r.CreateTimeout(ctx, plan.Timeouts) + _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ID.ValueString(), createTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForCreation, ResNameTLSInspectionConfiguration, plan.Name.String(), err), + err.Error(), + ) + return + } + + // TIP: -- 7. Save the request plan to response state + resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) +} + +func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + // TIP: ==== RESOURCE READ ==== + // Generally, the Read function should do the following things. Make + // sure there is a good reason if you don't do one of these. + // + // 1. Get a client connection to the relevant service + // 2. Fetch the state + // 3. Get the resource from AWS + // 4. Remove resource from state if it is not found + // 5. Set the arguments and attributes + // 6. Set the state + + // TIP: -- 1. Get a client connection to the relevant service + conn := r.Meta().NetworkFirewallConn(ctx) + + // TIP: -- 2. Fetch the state + var state resourceTLSInspectionConfigurationData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + // TIP: -- 3. Get the resource from AWS using an API Get, List, or Describe- + // type function, or, better yet, using a finder. + out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, state.ARN.ValueString(), state.Name.ValueString()) + // TIP: -- 4. Remove resource from state if it is not found + if tfresource.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionSetting, ResNameTLSInspectionConfiguration, state.ID.String(), err), + err.Error(), + ) + return + } + + // TIP: -- 5. Set the arguments and attributes + // + // For simple data types (i.e., schema.StringAttribute, schema.BoolAttribute, + // schema.Int64Attribute, and schema.Float64Attribue), simply setting the + // appropriate data struct field is sufficient. The flex package implements + // helpers for converting between Go and Plugin-Framework types seamlessly. No + // error or nil checking is necessary. + // + // However, there are some situations where more handling is needed such as + // complex data types (e.g., schema.ListAttribute, schema.SetAttribute). In + // these cases the flatten function may have a diagnostics return value, which + // should be appended to resp.Diagnostics. + state.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) + state.Description = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.Description) + state.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) + state.Name = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationName) + + state.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) + state.NumberOfAssociations = flex.Int64ToFramework(ctx, out.TLSInspectionConfigurationResponse.NumberOfAssociations) + state.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) + + // Complex types + encryptionConfiguration, d := flattenEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) + resp.Diagnostics.Append(d...) + state.EncryptionConfiguration = encryptionConfiguration + + certificateAuthority, d := flattenCertificateAuthority(ctx, out.TLSInspectionConfigurationResponse.CertificateAuthority) + resp.Diagnostics.Append(d...) + state.CertificateAuthority = certificateAuthority + + certificates, d := flattenCertificates(ctx, out.TLSInspectionConfigurationResponse.Certificates) + resp.Diagnostics.Append(d...) + state.Certificates = certificates + + // TIP: Setting a complex type. + // complexArgument, d := flattenComplexArgument(ctx, out.ComplexArgument) + // resp.Diagnostics.Append(d...) + // state.ComplexArgument = complexArgument + + // TIP: -- 6. Set the state + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + // TIP: ==== RESOURCE UPDATE ==== + // Not all resources have Update functions. There are a few reasons: + // a. The AWS API does not support changing a resource + // b. All arguments have RequiresReplace() plan modifiers + // c. The AWS API uses a create call to modify an existing resource + // + // In the cases of a. and b., the resource will not have an update method + // defined. In the case of c., Update and Create can be refactored to call + // the same underlying function. + // + // The rest of the time, there should be an Update function and it should + // do the following things. Make sure there is a good reason if you don't + // do one of these. + // + // 1. Get a client connection to the relevant service + // 2. Fetch the plan and state + // 3. Populate a modify input structure and check for changes + // 4. Call the AWS modify/update function + // 5. Use a waiter to wait for update to complete + // 6. Save the request plan to response state + // TIP: -- 1. Get a client connection to the relevant service + conn := r.Meta().NetworkFirewallConn(ctx) + + // TIP: -- 2. Fetch the plan + var plan, state resourceTLSInspectionConfigurationData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + // TIP: -- 3. Populate a modify input structure and check for changes + if !plan.Name.Equal(state.Name) || + !plan.Description.Equal(state.Description) || + !plan.ComplexArgument.Equal(state.ComplexArgument) || + !plan.Type.Equal(state.Type) { + + in := &networkfirewall.UpdateTLSInspectionConfigurationInput{ + // TIP: Mandatory or fields that will always be present can be set when + // you create the Input structure. (Replace these with real fields.) + TLSInspectionConfigurationId: aws.String(plan.ID.ValueString()), + TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), + TLSInspectionConfigurationType: aws.String(plan.Type.ValueString()), + } + + if !plan.Description.IsNull() { + // TIP: Optional fields should be set based on whether or not they are + // used. + in.Description = aws.String(plan.Description.ValueString()) + } + if !plan.ComplexArgument.IsNull() { + // TIP: Use an expander to assign a complex argument. The elements must be + // deserialized into the appropriate struct before being passed to the expander. + var tfList []complexArgumentData + resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) + if resp.Diagnostics.HasError() { + return + } + + in.ComplexArgument = expandComplexArgument(tfList) + } + + // TIP: -- 4. Call the AWS modify/update function + out, err := conn.UpdateTLSInspectionConfiguration(ctx, in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionUpdating, ResNameTLSInspectionConfiguration, plan.ID.String(), err), + err.Error(), + ) + return + } + if out == nil || out.TLSInspectionConfiguration == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionUpdating, ResNameTLSInspectionConfiguration, plan.ID.String(), nil), + errors.New("empty output").Error(), + ) + return + } + + // TIP: Using the output from the update function, re-set any computed attributes + plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfiguration.Arn) + plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfiguration.TLSInspectionConfigurationId) + } + + + // TIP: -- 5. Use a waiter to wait for update to complete + updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) + _, err := waitTLSInspectionConfigurationUpdated(ctx, conn, plan.ID.ValueString(), updateTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForUpdate, ResNameTLSInspectionConfiguration, plan.ID.String(), err), + err.Error(), + ) + return + } + + + // TIP: -- 6. Save the request plan to response state + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + // TIP: -- 1. Get a client connection to the relevant service + conn := r.Meta().NetworkFirewallConn(ctx) + + // TIP: -- 2. Fetch the state + var state resourceTLSInspectionConfigurationData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + // TIP: -- 3. Populate a delete input structure + in := &networkfirewall.DeleteTLSInspectionConfigurationInput{ + TLSInspectionConfigurationArn: aws.String(state.ARN.ValueString()), + } + + // TIP: -- 4. Call the AWS delete function + _, err := conn.DeleteTLSInspectionConfigurationWithContext(ctx, in) + // TIP: On rare occassions, the API returns a not found error after deleting a + // resource. If that happens, we don't want it to show up as an error. + if err != nil { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionDeleting, ResNameTLSInspectionConfiguration, state.ID.String(), err), + err.Error(), + ) + return + } + + // TIP: -- 5. Use a waiter to wait for delete to complete + deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) + _, err = waitTLSInspectionConfigurationDeleted(ctx, conn, state.ID.ValueString(), deleteTimeout) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForDeletion, ResNameTLSInspectionConfiguration, state.ID.String(), err), + err.Error(), + ) + return + } +} + +// TIP: ==== TERRAFORM IMPORTING ==== +// If Read can get all the information it needs from the Identifier +// (i.e., path.Root("id")), you can use the PassthroughID importer. Otherwise, +// you'll need a custom import function. +// +// See more: +// https://developer.hashicorp.com/terraform/plugin/framework/resources/import +func (r *resourceTLSInspectionConfiguration) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + + +// TIP: ==== STATUS CONSTANTS ==== +// Create constants for states and statuses if the service does not +// already have suitable constants. We prefer that you use the constants +// provided in the service if available (e.g., awstypes.StatusInProgress). +const ( + statusChangePending = "Pending" + statusDeleting = "Deleting" + statusNormal = "Normal" + statusUpdated = "Updated" +) + +// TIP: ==== WAITERS ==== +// Some resources of some services have waiters provided by the AWS API. +// Unless they do not work properly, use them rather than defining new ones +// here. +// +// Sometimes we define the wait, status, and find functions in separate +// files, wait.go, status.go, and find.go. Follow the pattern set out in the +// service and define these where it makes the most sense. +// +// If these functions are used in the _test.go file, they will need to be +// exported (i.e., capitalized). +// +// You will need to adjust the parameters and names to fit the service. +func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.Client, id string, timeout time.Duration) (*awstypes.TLSInspectionConfiguration, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{}, + Target: []string{statusNormal}, + Refresh: statusTLSInspectionConfiguration(ctx, conn, id), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*networkfirewall.TLSInspectionConfiguration); ok { + return out, err + } + + return nil, err +} + +// TIP: It is easier to determine whether a resource is updated for some +// resources than others. The best case is a status flag that tells you when +// the update has been fully realized. Other times, you can check to see if a +// key resource argument is updated to a new value or not. +func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.Client, id string, timeout time.Duration) (*awstypes.TLSInspectionConfiguration, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{statusChangePending}, + Target: []string{statusUpdated}, + Refresh: statusTLSInspectionConfiguration(ctx, conn, id), + Timeout: timeout, + NotFoundChecks: 20, + ContinuousTargetOccurence: 2, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*networkfirewall.TLSInspectionConfiguration); ok { + return out, err + } + + return nil, err +} + +// TIP: A deleted waiter is almost like a backwards created waiter. There may +// be additional pending states, however. +func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.Client, id string, timeout time.Duration) (*awstypes.TLSInspectionConfiguration, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{statusDeleting, statusNormal}, + Target: []string{}, + Refresh: statusTLSInspectionConfiguration(ctx, conn, id), + Timeout: timeout, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if out, ok := outputRaw.(*networkfirewall.TLSInspectionConfiguration); ok { + return out, err + } + + return nil, err +} + +// TIP: ==== STATUS ==== +// The status function can return an actual status when that field is +// available from the API (e.g., out.Status). Otherwise, you can use custom +// statuses to communicate the states of the resource. +// +// Waiters consume the values returned by status functions. Design status so +// that it can be reused by a create, update, and delete waiter, if possible. +func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.Client, id string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := findTLSInspectionConfigurationByID(ctx, conn, id) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + return out, aws.ToString(out.Status), nil + } +} + +// TIP: ==== FINDERS ==== +// The find function is not strictly necessary. You could do the API +// request from the status function. However, we have found that find often +// comes in handy in other places besides the status function. As a result, it +// is good practice to define it separately. +func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, name string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { + in := &networkfirewall.DescribeTLSInspectionConfigurationInput{ + TLSInspectionConfigurationArn: aws.String(arn), + TLSInspectionConfigurationName: aws.String(name), + } + + out, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, in) + if err != nil { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + return nil, err + } + + if out == nil || out.TLSInspectionConfigurationResponse == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + +// TIP: ==== FLEX ==== +// Flatteners and expanders ("flex" functions) help handle complex data +// types. Flatteners take an API data type and return the equivalent Plugin-Framework +// type. In other words, flatteners translate from AWS -> Terraform. +// +// On the other hand, expanders take a Terraform data structure and return +// something that you can send to the AWS API. In other words, expanders +// translate from Terraform -> AWS. +// +// See more: +// https://hashicorp.github.io/terraform-provider-aws/data-handling-and-conversion/ +func flattenComplexArgument(ctx context.Context, apiObject *awstypes.ComplexArgument) (types.List, diag.Diagnostics) { + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} + + if apiObject == nil { + return types.ListNull(elemType), diags + } + + obj := map[string]attr.Value{ + "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), + "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), + } + objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) + diags.Append(d...) + + listVal, d := types.ListValue(elemType, []attr.Value{objVal}) + diags.Append(d...) + + return listVal, diags +} + +// TIP: Often the AWS API will return a slice of structures in response to a +// request for information. Sometimes you will have set criteria (e.g., the ID) +// that means you'll get back a one-length slice. This plural function works +// brilliantly for that situation too. +func flattenComplexArguments(ctx context.Context, apiObjects []*awstypes.ComplexArgument) (types.List, diag.Diagnostics) { + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} + + if len(apiObjects) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + obj := map[string]attr.Value{ + "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), + "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), + } + objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) + diags.Append(d...) + + elems = append(elems, objVal) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags +} + +// TIP: Remember, as mentioned above, expanders take a Terraform data structure +// and return something that you can send to the AWS API. In other words, +// expanders translate from Terraform -> AWS. +// +// See more: +// https://hashicorp.github.io/terraform-provider-aws/data-handling-and-conversion/ +func expandComplexArgument(tfList []complexArgumentData) *awstypes.ComplexArgument { + if len(tfList) == 0 { + return nil + } + + tfObj := tfList[0] + apiObject := &awstypes.ComplexArgument{ + NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), + } + if !tfObj.NestedOptional.IsNull() { + apiObject.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) + } + + return apiObject +} + +// TIP: Even when you have a list with max length of 1, this plural function +// works brilliantly. However, if the AWS API takes a structure rather than a +// slice of structures, you will not need it. +func expandComplexArguments(tfList []complexArgumentData) []*networkfirewall.ComplexArgument { + // TIP: The AWS API can be picky about whether you send a nil or zero- + // length for an argument that should be cleared. For example, in some + // cases, if you send a nil value, the AWS API interprets that as "make no + // changes" when what you want to say is "remove everything." Sometimes + // using a zero-length list will cause an error. + // + // As a result, here are two options. Usually, option 1, nil, will work as + // expected, clearing the field. But, test going from something to nothing + // to make sure it works. If not, try the second option. + // TIP: Option 1: Returning nil for zero-length list + if len(tfList) == 0 { + return nil + } + var apiObject []*awstypes.ComplexArgument + // TIP: Option 2: Return zero-length list for zero-length list. If option 1 does + // not work, after testing going from something to nothing (if that is + // possible), uncomment out the next line and remove option 1. + // + // apiObject := make([]*networkfirewall.ComplexArgument, 0) + + for _, tfObj := range tfList { + item := &networkfirewall.ComplexArgument{ + NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), + } + if !tfObj.NestedOptional.IsNull() { + item.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) + } + + apiObject = append(apiObject, item) + } + + return apiObject +} + +// TIP: ==== DATA STRUCTURES ==== +// With Terraform Plugin-Framework configurations are deserialized into +// Go types, providing type safety without the need for type assertions. +// These structs should match the schema definition exactly, and the `tfsdk` +// tag value should match the attribute name. +// +// Nested objects are represented in their own data struct. These will +// also have a corresponding attribute type mapping for use inside flex +// functions. +// +// See more: +// https://developer.hashicorp.com/terraform/plugin/framework/handling-data/accessing-values +type resourceTLSInspectionConfigurationData struct { + ARN types.String `tfsdk:"arn"` + EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` + Certificates types.List `tfsdk:"certificates"` + CertificateAuthority types.List `tfsdk:"certificate_authority"` + ComplexArgument types.List `tfsdk:"complex_argument"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + LastModifiedTime types.String `tfsdk:"last_modified_time"` + Name types.String `tfsdk:"name"` + NumberOfAssociations types.Int64 `tfsdk:"number_of_associations"` + Status types.String `tfsdk:"status"` + TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + Type types.String `tfsdk:"type"` + UpdateToken types.String `tfsdk:"update_token"` +} + + +// "last_modified_time": schema.StringAttribute{ +// Computed: true, +// }, +// "number_of_associations": schema.Int64Attribute{ +// Computed: true, +// }, +// "status": schema.StringAttribute{ +// Computed: true, +// }, +// "update_token": schema.StringAttribute{ +// Computed: true, + +type complexArgumentData struct { + NestedRequired types.String `tfsdk:"nested_required"` + NestedOptional types.String `tfsdk:"nested_optional"` +} + +var complexArgumentAttrTypes = map[string]attr.Type{ + "nested_required": types.StringType, + "nested_optional": types.StringType, +} + +var encryptionConfigurationAttrTypes = map[string]attr.Type{ + "type": types.StringType, + "key_id": types.StringType, +} \ No newline at end of file diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go new file mode 100644 index 00000000000..00660a412b0 --- /dev/null +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -0,0 +1,332 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package networkfirewall_test +// **PLEASE DELETE THIS AND ALL TIP COMMENTS BEFORE SUBMITTING A PR FOR REVIEW!** +// +// TIP: ==== INTRODUCTION ==== +// Thank you for trying the skaff tool! +// +// You have opted to include these helpful comments. They all include "TIP:" +// to help you find and remove them when you're done with them. +// +// While some aspects of this file are customized to your input, the +// scaffold tool does *not* look at the AWS API and ensure it has correct +// function, structure, and variable names. It makes guesses based on +// commonalities. You will need to make significant adjustments. +// +// In other words, as generated, this is a rough outline of the work you will +// need to do. If something doesn't make sense for your situation, get rid of +// it. + +import ( + // TIP: ==== IMPORTS ==== + // This is a common set of imports but not customized to your code since + // your code hasn't been written yet. Make sure you, your IDE, or + // goimports -w fixes these imports. + // + // The provider linter wants your imports to be in two groups: first, + // standard library (i.e., "fmt" or "strings"), second, everything else. + // + // Also, AWS Go SDK v2 may handle nested structures differently than v1, + // using the services/networkfirewall/types package. If so, you'll + // need to import types and reference the nested types, e.g., as + // types.. + "context" + "errors" + "fmt" + "testing" + + "github.com/YakDriver/regexache" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/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" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/names" + + // TIP: You will often need to import the package that this test file lives + // in. Since it is in the "test" context, it must import the package to use + // any normal context constants, variables, or functions. + tfnetworkfirewall "github.com/hashicorp/terraform-provider-aws/internal/service/networkfirewall" +) + +// TIP: File Structure. The basic outline for all test files should be as +// follows. Improve this resource's maintainability by following this +// outline. +// +// 1. Package declaration (add "_test" since this is a test file) +// 2. Imports +// 3. Unit tests +// 4. Basic test +// 5. Disappears test +// 6. All the other tests +// 7. Helper functions (exists, destroy, check, etc.) +// 8. Functions that return Terraform configurations + +// TIP: ==== UNIT TESTS ==== +// This is an example of a unit test. Its name is not prefixed with +// "TestAcc" like an acceptance test. +// +// Unlike acceptance tests, unit tests do not access AWS and are focused on a +// function (or method). Because of this, they are quick and cheap to run. +// +// In designing a resource's implementation, isolate complex bits from AWS bits +// so that they can be tested through a unit test. We encourage more unit tests +// in the provider. +// +// Cut and dry functions using well-used patterns, like typical flatteners and +// expanders, don't need unit testing. However, if they are complex or +// intricate, they should be unit tested. +func TestTLSInspectionConfigurationExampleUnitTest(t *testing.T) { + t.Parallel() + + testCases := []struct { + TestName string + Input string + Expected string + Error bool + }{ + { + TestName: "empty", + Input: "", + Expected: "", + Error: true, + }, + { + TestName: "descriptive name", + Input: "some input", + Expected: "some output", + Error: false, + }, + { + TestName: "another descriptive name", + Input: "more input", + Expected: "more output", + Error: false, + }, + } + + for _, testCase := range testCases { + testCase := testCase + t.Run(testCase.TestName, func(t *testing.T) { + t.Parallel() + got, err := tfnetworkfirewall.FunctionFromResource(testCase.Input) + + if err != nil && !testCase.Error { + t.Errorf("got error (%s), expected no error", err) + } + + if err == nil && testCase.Error { + t.Errorf("got (%s) and no error, expected error", got) + } + + if got != testCase.Expected { + t.Errorf("got %s, expected %s", got, testCase.Expected) + } + }) + } +} + +// TIP: ==== ACCEPTANCE TESTS ==== +// This is an example of a basic acceptance test. This should test as much of +// standard functionality of the resource as possible, and test importing, if +// applicable. We prefix its name with "TestAcc", the service, and the +// resource name. +// +// Acceptance test access AWS and cost money to run. +func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { + ctx := acctest.Context(t) + // TIP: This is a long-running test guard for tests that run longer than + // 300s (5 min) generally. + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationResponse + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.NetworkFirewallEndpointID) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewallEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), + resource.TestCheckResourceAttrSet(resourceName, "maintenance_window_start_time.0.day_of_week"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "user.*", map[string]string{ + "console_access": "false", + "groups.#": "0", + "username": "Test", + "password": "TestTest1234", + }), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "networkfirewall", regexache.MustCompile(`tlsinspectionconfiguration:+.`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, + }, + }) +} + +func TestAccNetworkFirewallTLSInspectionConfiguration_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationResponse + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.NetworkFirewallEndpointID) + testAccPreCheck(t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewallEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_basic(rName, testAccTLSInspectionConfigurationVersionNewer), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), + // TIP: The Plugin-Framework disappears helper is similar to the Plugin-SDK version, + // but expects a new resource factory function as the third argument. To expose this + // private function to the testing package, you may need to add a line like the following + // to exports_test.go: + // + // var ResourceTLSInspectionConfiguration = newResourceTLSInspectionConfiguration + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfnetworkfirewall.ResourceTLSInspectionConfiguration, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_networkfirewall_tls_inspection_configuration" { + continue + } + + input := &networkfirewall.DescribeTLSInspectionConfigurationInput{ + TLSInspectionConfigurationId: aws.String(rs.Primary.ID), + } + _, err := conn.DescribeTLSInspectionConfiguration(ctx, &networkfirewall.DescribeTLSInspectionConfigurationInput{ + TLSInspectionConfigurationId: aws.String(rs.Primary.ID), + }) + if errs.IsA[*types.ResourceNotFoundException](err){ + return nil + } + if err != nil { + return create.Error(names.NetworkFirewall, create.ErrActionCheckingDestroyed, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, err) + } + + return create.Error(names.NetworkFirewall, create.ErrActionCheckingDestroyed, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name string, tlsinspectionconfiguration *networkfirewall.DescribeTLSInspectionConfigurationResponse) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.NetworkFirewall, create.ErrActionCheckingExistence, tfnetworkfirewall.ResNameTLSInspectionConfiguration, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.NetworkFirewall, create.ErrActionCheckingExistence, tfnetworkfirewall.ResNameTLSInspectionConfiguration, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) + resp, err := conn.DescribeTLSInspectionConfiguration(ctx, &networkfirewall.DescribeTLSInspectionConfigurationInput{ + TLSInspectionConfigurationId: aws.String(rs.Primary.ID), + }) + + if err != nil { + return create.Error(names.NetworkFirewall, create.ErrActionCheckingExistence, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, err) + } + + *tlsinspectionconfiguration = *resp + + return nil + } +} + +func testAccPreCheck(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) + + input := &networkfirewall.ListTLSInspectionConfigurationsInput{} + _, err := conn.ListTLSInspectionConfigurations(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccCheckTLSInspectionConfigurationNotRecreated(before, after *networkfirewall.DescribeTLSInspectionConfigurationResponse) resource.TestCheckFunc { + return func(s *terraform.State) error { + if before, after := aws.ToString(before.TLSInspectionConfigurationId), aws.ToString(after.TLSInspectionConfigurationId); before != after { + return create.Error(names.NetworkFirewall, create.ErrActionCheckingNotRecreated, tfnetworkfirewall.ResNameTLSInspectionConfiguration, aws.ToString(before.TLSInspectionConfigurationId), errors.New("recreated")) + } + + return nil + } +} + +func testAccTLSInspectionConfigurationConfig_basic(rName, version string) string { + return fmt.Sprintf(` +resource "aws_security_group" "test" { + name = %[1]q +} + +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + tls_inspection_configuration_name = %[1]q + engine_type = "ActiveNetworkFirewall" + engine_version = %[2]q + host_instance_type = "networkfirewall.t2.micro" + security_groups = [aws_security_group.test.id] + authentication_strategy = "simple" + storage_type = "efs" + + logs { + general = true + } + + user { + username = "Test" + password = "TestTest1234" + } +} +`, rName, version) +} From 165441221270a4c02559a19dc4dbb565667ecdb2 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:09:06 -0500 Subject: [PATCH 02/68] [WIP] Flex functions --- .../tls_inspection_configuration.go | 263 +++++++++++++++--- 1 file changed, 232 insertions(+), 31 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index e3f66b021fe..88ed72b9767 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -456,14 +456,15 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou state.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) state.NumberOfAssociations = flex.Int64ToFramework(ctx, out.TLSInspectionConfigurationResponse.NumberOfAssociations) + state.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) state.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) // Complex types - encryptionConfiguration, d := flattenEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) + encryptionConfiguration, d := flattenTLSEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) resp.Diagnostics.Append(d...) state.EncryptionConfiguration = encryptionConfiguration - certificateAuthority, d := flattenCertificateAuthority(ctx, out.TLSInspectionConfigurationResponse.CertificateAuthority) + certificateAuthority, d := flattenTLSCertificate(ctx, out.TLSInspectionConfigurationResponse.CertificateAuthority) resp.Diagnostics.Append(d...) state.CertificateAuthority = certificateAuthority @@ -803,6 +804,180 @@ func flattenComplexArgument(ctx context.Context, apiObject *awstypes.ComplexArgu return listVal, diags } + +func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: certificateAttrTypes} + + if len(certificateList) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, certificate := range certificateList { + if certificate == nil { + continue + } + flattenedCertificate, d := flattenTLSCertificate(ctx, certificate) + diags.Append(d...) + elems = append(elems, flattenedCertificate) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags +} + +func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: certificateAttrTypes} + + if certificate == nil { + return types.ListNull(elemType), diags + } + + obj := map[string]attr.Value{ + "certificate_arn": flex.StringToFramework(ctx, certificate.CertificateArn), + "certificate_serial": flex.StringToFramework(ctx, certificate.CertificateSerial), + "status": flex.StringToFramework(ctx, certificate.Status), + "status_message": flex.StringToFramework(ctx, certificate.StatusMessage), + } + objVal, d := types.ObjectValue(certificateAttrTypes, obj) + diags.Append(d...) + + listVal, d := types.ListValue(elemType, []attr.Value{objVal}) + diags.Append(d...) + + return listVal, diags + +} + + +func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertificateScope)(types.List, diag.Diagnostics){ + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: scopeAttrTypes} + + if len(scopes) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, scope := range scopes { + if scope == nil { + continue + } + + destinationPorts, d := flattenPortRange(ctx, scope.DestinationPorts) + destinations, d := flattenSourceDestinations(ctx, scope.Destinations) + sourcePorts, d := flattenPortRange(ctx, scope.SourcePorts) + sources, d := flattenSourceDestinations(ctx, scope.Sources) + + + obj := map[string]attr.Value{ + "destination_ports": destinationPorts, + "destinations": destinations, + // "protocols": flex. + "source_ports": sourcePorts, + "sources": sources, + } + objVal, d := types.ObjectValue(scopeAttrTypes, obj) + diags.Append(d...) + + elems = append(elems, objVal) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags + +} + + +func flattenSourceDestinations(ctx context.Context, destinations []*networkfirewall.Address) (types.List, diag.Diagnostics) { + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: sourceDestinationAttrTypes} + + if len(destinations) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, destination := range destinations { + if destination == nil { + continue + } + + obj := map[string]attr.Value{ + "address_definition": flex.StringToFramework(ctx, destination.AddressDefinition), + } + objVal, d := types.ObjectValue(sourceDestinationAttrTypes, obj) + diags.Append(d...) + + elems = append(elems, objVal) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags +} + +func flattenPortRange(ctx context.Context, ranges []*networkfirewall.PortRange) (types.List, diag.Diagnostics) { + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: portRangeAttrTypes} + + if len(ranges) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, portRange := range ranges { + if portRange == nil { + continue + } + + obj := map[string]attr.Value{ + "from_port": flex.Int64ToFramework(ctx, portRange.FromPort), + "to_port": flex.Int64ToFramework(ctx, portRange.ToPort), + } + objVal, d := types.ObjectValue(portRangeAttrTypes, obj) + diags.Append(d...) + + elems = append(elems, objVal) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags +} + +func flattenCheckCertificateRevocationStatus(){} + +func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfiguration *networkfirewall.EncryptionConfiguration) (types.List, diag.Diagnostics) { + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: encryptionConfigurationAttrTypes} + + if encryptionConfiguration == nil { + return types.ListNull(elemType), diags + } + + obj := map[string]attr.Value{ + "key_id": flex.StringToFramework(ctx, encryptionConfiguration.KeyId), + "type": flex.StringToFramework(ctx, encryptionConfiguration.Type), + } + objVal, d := types.ObjectValue(encryptionConfigurationAttrTypes, obj) + diags.Append(d...) + + listVal, d := types.ListValue(elemType, []attr.Value{objVal}) + diags.Append(d...) + + return listVal, diags + +} + // TIP: Often the AWS API will return a slice of structures in response to a // request for information. Sometimes you will have set criteria (e.g., the ID) // that means you'll get back a one-length slice. This plural function works @@ -910,41 +1085,51 @@ func expandComplexArguments(tfList []complexArgumentData) []*networkfirewall.Com // See more: // https://developer.hashicorp.com/terraform/plugin/framework/handling-data/accessing-values type resourceTLSInspectionConfigurationData struct { - ARN types.String `tfsdk:"arn"` - EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` - Certificates types.List `tfsdk:"certificates"` - CertificateAuthority types.List `tfsdk:"certificate_authority"` - ComplexArgument types.List `tfsdk:"complex_argument"` - Description types.String `tfsdk:"description"` - ID types.String `tfsdk:"id"` - LastModifiedTime types.String `tfsdk:"last_modified_time"` - Name types.String `tfsdk:"name"` - NumberOfAssociations types.Int64 `tfsdk:"number_of_associations"` - Status types.String `tfsdk:"status"` - TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` - Timeouts timeouts.Value `tfsdk:"timeouts"` - Type types.String `tfsdk:"type"` - UpdateToken types.String `tfsdk:"update_token"` -} - - -// "last_modified_time": schema.StringAttribute{ -// Computed: true, -// }, -// "number_of_associations": schema.Int64Attribute{ -// Computed: true, -// }, -// "status": schema.StringAttribute{ -// Computed: true, -// }, -// "update_token": schema.StringAttribute{ -// Computed: true, + ARN types.String `tfsdk:"arn"` + EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` + Certificates types.List `tfsdk:"certificates"` + CertificateAuthority types.List `tfsdk:"certificate_authority"` + // ComplexArgument types.List `tfsdk:"complex_argument"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + LastModifiedTime types.String `tfsdk:"last_modified_time"` + Name types.String `tfsdk:"name"` + NumberOfAssociations types.Int64 `tfsdk:"number_of_associations"` + Status types.String `tfsdk:"status"` + TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + Type types.String `tfsdk:"type"` + UpdateToken types.String `tfsdk:"update_token"` +} + +type encryptionConfigurationData struct { + Type types.String `tfsdk:"type"` + KeyId types.String `tfsdk:"key_id"` +} + +type certificatesData struct { + CertificateArn types.String `tfsdk:"certificate_arn"` + CertificateSerial types.String `tfsdk:"certificate_serial"` + Status types.String `tfsdk:"status"` + StatusMessage types.String `tfsdk:"status_message"` +} + +type tlsInspectionConfiguration struct { + ServerCertificateConfiguration types.List `tfsdk:"server_certificate_configuration"` +} type complexArgumentData struct { NestedRequired types.String `tfsdk:"nested_required"` NestedOptional types.String `tfsdk:"nested_optional"` } +var certificateAttrTypes = map[string]attr.Type{ + "certificate_arn": types.StringType, + "certificate_serial": types.StringType, + "status": types.StringType, + "status_message": types.StringType, +} + var complexArgumentAttrTypes = map[string]attr.Type{ "nested_required": types.StringType, "nested_optional": types.StringType, @@ -953,4 +1138,20 @@ var complexArgumentAttrTypes = map[string]attr.Type{ var encryptionConfigurationAttrTypes = map[string]attr.Type{ "type": types.StringType, "key_id": types.StringType, +} + +var scopeAttrTypes = map[string]attr.Type{ + "destination_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, + "destinations": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, + "source_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, + "sources": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, +} + +var sourceDestinationAttrTypes = map[string]attr.Type{ + "address_definition": types.StringType, +} + +var portRangeAttrTypes = map[string]attr.Type{ + "fromt_port": types.Int64Type, + "to_port": types.Int64Type, } \ No newline at end of file From 7b037cd3c113c7cec93beaf0ef041d4fc43dbf6c Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:25:38 -0500 Subject: [PATCH 03/68] [WIP] Flex functions and data structures --- .../tls_inspection_configuration.go | 323 ++++++++++++++---- 1 file changed, 253 insertions(+), 70 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 88ed72b9767..3bb18b1e307 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -339,25 +339,26 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res if !plan.TLSInspectionConfiguration.IsNull() { // TIP: Use an expander to assign a complex argument. The elements must be // deserialized into the appropriate struct before being passed to the expander. - var tfList []complexArgumentData - resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) + var tfList []tlsInspectionConfigurationData + resp.Diagnostics.Append(plan.TLSInspectionConfiguration.ElementsAs(ctx, &tfList, false)...) if resp.Diagnostics.HasError() { return } - in.TLSInspectionConfiguration = expandComplexArgument(tfList) + // in.TLSInspectionConfiguration = expandComplexArgument(tfList) + in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(tfList) } if !plan.EncryptionConfiguration.IsNull() { // TIP: Use an expander to assign a complex argument. The elements must be // deserialized into the appropriate struct before being passed to the expander. var tfList []complexArgumentData - resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) + resp.Diagnostics.Append(plan.EncryptionConfiguration.ElementsAs(ctx, &tfList, false)...) if resp.Diagnostics.HasError() { return } - in.TLSInspectionConfiguration = expandComplexArgument(tfList) + in.EncryptionConfiguration = expandEncryptionConfiguration(tfList) } // TIP: -- 4. Call the AWS create function @@ -423,7 +424,7 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou // TIP: -- 3. Get the resource from AWS using an API Get, List, or Describe- // type function, or, better yet, using a finder. - out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, state.ARN.ValueString(), state.Name.ValueString()) + out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, state.ARN.ValueString()) // TIP: -- 4. Remove resource from state if it is not found if tfresource.NotFound(err) { resp.State.RemoveResource(ctx) @@ -662,7 +663,7 @@ const ( // exported (i.e., capitalized). // // You will need to adjust the parameters and names to fit the service. -func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.Client, id string, timeout time.Duration) (*awstypes.TLSInspectionConfiguration, error) { +func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, id string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{}, Target: []string{statusNormal}, @@ -684,11 +685,11 @@ func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfir // resources than others. The best case is a status flag that tells you when // the update has been fully realized. Other times, you can check to see if a // key resource argument is updated to a new value or not. -func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.Client, id string, timeout time.Duration) (*awstypes.TLSInspectionConfiguration, error) { +func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{statusChangePending}, Target: []string{statusUpdated}, - Refresh: statusTLSInspectionConfiguration(ctx, conn, id), + Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), Timeout: timeout, NotFoundChecks: 20, ContinuousTargetOccurence: 2, @@ -704,7 +705,7 @@ func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfir // TIP: A deleted waiter is almost like a backwards created waiter. There may // be additional pending states, however. -func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.Client, id string, timeout time.Duration) (*awstypes.TLSInspectionConfiguration, error) { +func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, id string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{statusDeleting, statusNormal}, Target: []string{}, @@ -727,9 +728,9 @@ func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfir // // Waiters consume the values returned by status functions. Design status so // that it can be reused by a create, update, and delete waiter, if possible. -func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.Client, id string) retry.StateRefreshFunc { +func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - out, err := findTLSInspectionConfigurationByID(ctx, conn, id) + out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, arn) if tfresource.NotFound(err) { return nil, "", nil } @@ -738,7 +739,7 @@ func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall return nil, "", err } - return out, aws.ToString(out.Status), nil + return out, aws.ToString(out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus), nil } } @@ -747,10 +748,9 @@ func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall // request from the status function. However, we have found that find often // comes in handy in other places besides the status function. As a result, it // is good practice to define it separately. -func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, name string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { +func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { in := &networkfirewall.DescribeTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(arn), - TLSInspectionConfigurationName: aws.String(name), } out, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, in) @@ -783,26 +783,26 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo // // See more: // https://hashicorp.github.io/terraform-provider-aws/data-handling-and-conversion/ -func flattenComplexArgument(ctx context.Context, apiObject *awstypes.ComplexArgument) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} +// func flattenComplexArgument(ctx context.Context, apiObject *awstypes.ComplexArgument) (types.List, diag.Diagnostics) { +// var diags diag.Diagnostics +// elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} - if apiObject == nil { - return types.ListNull(elemType), diags - } +// if apiObject == nil { +// return types.ListNull(elemType), diags +// } - obj := map[string]attr.Value{ - "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), - "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), - } - objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) - diags.Append(d...) +// obj := map[string]attr.Value{ +// "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), +// "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), +// } +// objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) +// diags.Append(d...) - listVal, d := types.ListValue(elemType, []attr.Value{objVal}) - diags.Append(d...) +// listVal, d := types.ListValue(elemType, []attr.Value{objVal}) +// diags.Append(d...) - return listVal, diags -} +// return listVal, diags +// } func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ @@ -982,35 +982,35 @@ func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfigurat // request for information. Sometimes you will have set criteria (e.g., the ID) // that means you'll get back a one-length slice. This plural function works // brilliantly for that situation too. -func flattenComplexArguments(ctx context.Context, apiObjects []*awstypes.ComplexArgument) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} +// func flattenComplexArguments(ctx context.Context, apiObjects []*awstypes.ComplexArgument) (types.List, diag.Diagnostics) { +// var diags diag.Diagnostics +// elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} - if len(apiObjects) == 0 { - return types.ListNull(elemType), diags - } +// if len(apiObjects) == 0 { +// return types.ListNull(elemType), diags +// } - elems := []attr.Value{} - for _, apiObject := range apiObjects { - if apiObject == nil { - continue - } +// elems := []attr.Value{} +// for _, apiObject := range apiObjects { +// if apiObject == nil { +// continue +// } - obj := map[string]attr.Value{ - "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), - "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), - } - objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) - diags.Append(d...) +// obj := map[string]attr.Value{ +// "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), +// "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), +// } +// objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) +// diags.Append(d...) - elems = append(elems, objVal) - } +// elems = append(elems, objVal) +// } - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) +// listVal, d := types.ListValue(elemType, elems) +// diags.Append(d...) - return listVal, diags -} +// return listVal, diags +// } // TIP: Remember, as mentioned above, expanders take a Terraform data structure // and return something that you can send to the AWS API. In other words, @@ -1034,6 +1034,131 @@ func expandComplexArgument(tfList []complexArgumentData) *awstypes.ComplexArgume return apiObject } +func expandTLSInspectionConfiguration(tfList []tlsInspectionConfigurationData) []networkfirewall.TLSInspectionConfiguration { + var apiObject []networkfirewall.TLSInspectionConfiguration + + for _, item := range tfList { + conf := networkfirewall.TLSInspectionConfiguration{} + if !item.ServerCertificateConfiguration.IsNull() { + var serverConfig []serverCertificateConfigurationsData + conf.ServerCertificateConfigurations = expandServerCertificateConfigurations(serverConfig) + } + + apiObject = append(apiObject, conf) + } + return apiObject +} + +func expandServerCertificateConfigurations(tfList []serverCertificateConfigurationsData) []*networkfirewall.ServerCertificateConfiguration { + var apiObject []*networkfirewall.ServerCertificateConfiguration + + for _, item := range tfList { + conf := &networkfirewall.ServerCertificateConfiguration{ + CertificateAuthorityArn: aws.String(item.CertificateAuthorityArn.ValueString()), + } + if !item.CheckCertificateRevocationsStatus.IsNull() { + var certificateRevocationStatus []checkCertificateRevocationStatusData + conf.CheckCertificateRevocationStatus = expandCheckCertificateRevocationStatus(certificateRevocationStatus) + } + if !item.Scopes.IsNull() { + var scopesList []scopeData + conf.Scopes = expandScopes(scopesList) + } + if !item.ServerCertificates.IsNull() { + var serverCertificates []serverCertificatesData + conf.ServerCertificates = expandServerCertificates(serverCertificates) + } + + apiObject = append(apiObject, conf) + } + return apiObject +} + +func expandCheckCertificateRevocationStatus(tfList []checkCertificateRevocationStatusData) *networkfirewall.CheckCertificateRevocationStatusActions{ + if len(tfList) == 0 { + return nil + } + + tfObj := tfList[0] + apiObject := &networkfirewall.CheckCertificateRevocationStatusActions{ + RevokedStatusAction: aws.String(tfObj.RevokedStatusAction.ValueString()), + UnknownStatusAction: aws.String(tfObj.UnknownStatusAction.ValueString()), + } + return apiObject +} + +func expandServerCertificates(tfList []serverCertificatesData) []*networkfirewall.ServerCertificate { + var apiObject []*networkfirewall.ServerCertificate + + for _, item := range tfList { + conf := &networkfirewall.ServerCertificate{ + ResourceArn: aws.String(item.ResourceARN.ValueString()), + } + + apiObject = append(apiObject, conf) + } + return apiObject +} + +func expandScopes(tfList []scopeData) []*networkfirewall.ServerCertificateScope { + var apiObject []*networkfirewall.ServerCertificateScope + + for _, tfObj := range tfList { + item := &networkfirewall.ServerCertificateScope{ + // Protocols: + } + if !tfObj.DestinationPorts.IsNull() { + var destinationPorts []portRangeData + item.DestinationPorts = expandPortRange(destinationPorts) + } + if !tfObj.Destinations.IsNull() { + var destinations []sourceDestinationData + item.Destinations = expandSourceDestinations(destinations) + } + if !tfObj.SourcePorts.IsNull() { + var sourcePorts []portRangeData + item.SourcePorts = expandPortRange(sourcePorts) + } + if !tfObj.Sources.IsNull() { + var sources []sourceDestinationData + item.Sources = expandSourceDestinations(sources) + } + apiObject = append(apiObject, item) + } + + return apiObject +} + +func expandPortRange(tfList []portRangeData) []*networkfirewall.PortRange { + var apiObject []*networkfirewall.PortRange + + for _, tfObj := range tfList { + item := &networkfirewall.PortRange{ + FromPort: aws.Int64(tfObj.FromPort.ValueInt64()), + ToPort: aws.Int64(tfObj.ToPort.ValueInt64()), + } + apiObject = append(apiObject, item) + } + + return apiObject +} + +func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall.Address { + var apiObject []*networkfirewall.Address + + for _, tfObj := range tfList { + item := &networkfirewall.Address{ + AddressDefinition: aws.String(tfObj.AddressDefinition.ValueString()), + } + apiObject = append(apiObject, item) + } + + return apiObject +} + + + + // TIP: Even when you have a list with max length of 1, this plural function // works brilliantly. However, if the AWS API takes a structure rather than a // slice of structures, you will not need it. @@ -1114,44 +1239,102 @@ type certificatesData struct { StatusMessage types.String `tfsdk:"status_message"` } -type tlsInspectionConfiguration struct { +type tlsInspectionConfigurationData struct { ServerCertificateConfiguration types.List `tfsdk:"server_certificate_configuration"` } +type serverCertificateConfigurationsData struct { + CertificateAuthorityArn types.String `tfsdk:"certificate_authority_arn"` + CheckCertificateRevocationsStatus types.List `tfsdk:"check_certificate_revocations_status"` + Scopes types.List `tfsdk:"scopes"` + ServerCertificates types.List `tfsdk:"server_certificates"` +} + type complexArgumentData struct { NestedRequired types.String `tfsdk:"nested_required"` NestedOptional types.String `tfsdk:"nested_optional"` } -var certificateAttrTypes = map[string]attr.Type{ +type scopeData struct { + DestinationPorts types.List `tfsdk:"destination_ports"` + Destinations types.List `tfsdk:"destinations"` + Protocols types.List `tfsdk:"protocols"` + SourcePorts types.List `tfsdk:"source_ports"` + Sources types.List `tfsdk:"sources"` +} + +type sourceDestinationData struct { + AddressDefinition types.String `tfsdk:"address_definition"` +} + +type portRangeData struct { + FromPort types.Int64 `tfsdk:"from_port"` + ToPort types.Int64 `tfsdk:"to_port"` +} + +type checkCertificateRevocationStatusData struct { + RevokedStatusAction types.String `tfsdk:"revoked_status_action"` + UnknownStatusAction types.String `tfsdk:"unknown_status_action"` +} + +type serverCertificatesData struct { + ResourceARN types.String `tfsdk:"resource_arn"` +} + +////////////// + +var certificatesAttrTypes = map[string]attr.Type{ "certificate_arn": types.StringType, "certificate_serial": types.StringType, "status": types.StringType, "status_message": types.StringType, } -var complexArgumentAttrTypes = map[string]attr.Type{ - "nested_required": types.StringType, - "nested_optional": types.StringType, -} +// var complexArgumentAttrTypes = map[string]attr.Type{ +// "nested_required": types.StringType, +// "nested_optional": types.StringType, +// } var encryptionConfigurationAttrTypes = map[string]attr.Type{ "type": types.StringType, "key_id": types.StringType, } -var scopeAttrTypes = map[string]attr.Type{ - "destination_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, - "destinations": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, - "source_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, - "sources": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, +var tlsInspectionConfigurationAttrTypes = map[string]attr.Type{ + "server_certificate_configuration": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes}}, +} + +var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ + "certificate_authority_arn": types.StringType, + "check_certificate_revocations_status": types.ListType{ElemType: types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes}}, + "scopes": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, + "server_certificates": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificatesAttrTypes}}, } -var sourceDestinationAttrTypes = map[string]attr.Type{ - "address_definition": types.StringType, +var checkCertificateRevocationStatusAttrTypes = map[string]attr.Type{ + "revoked_status_action": types.StringType, + "unknown_status_action": types.StringType, } -var portRangeAttrTypes = map[string]attr.Type{ - "fromt_port": types.Int64Type, - "to_port": types.Int64Type, +var ( + scopeAttrTypes = map[string]attr.Type{ + "destination_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, + "destinations": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, + "protocols": types.ListType{ElemType: types.Int64Type}, + "source_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, + "sources": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, + } + + sourceDestinationAttrTypes = map[string]attr.Type{ + "address_definition": types.StringType, + } + + portRangeAttrTypes = map[string]attr.Type{ + "from_port": types.Int64Type, + "to_port": types.Int64Type, + } +) + +var serverCertificatesAttrTypes = map[string]attr.Type{ + "resource_arn": types.StringType, } \ No newline at end of file From c06674aed3e4fd9472ed1fe150973f8c97f7ca25 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 5 Jan 2024 14:10:53 -0500 Subject: [PATCH 04/68] Finish first pass at CRUD, flex functions --- .../tls_inspection_configuration.go | 187 +++++++++++------- 1 file changed, 116 insertions(+), 71 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 3bb18b1e307..d627a84bc2e 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -207,7 +207,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "protocols": schema.ListAttribute{ - ElementType: types.StringType, + ElementType: types.Int64Type, Required: true, }, }, @@ -352,13 +352,13 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res if !plan.EncryptionConfiguration.IsNull() { // TIP: Use an expander to assign a complex argument. The elements must be // deserialized into the appropriate struct before being passed to the expander. - var tfList []complexArgumentData + var tfList []encryptionConfigurationData resp.Diagnostics.Append(plan.EncryptionConfiguration.ElementsAs(ctx, &tfList, false)...) if resp.Diagnostics.HasError() { return } - in.EncryptionConfiguration = expandEncryptionConfiguration(tfList) + in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) } // TIP: -- 4. Call the AWS create function @@ -515,17 +515,17 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res } // TIP: -- 3. Populate a modify input structure and check for changes - if !plan.Name.Equal(state.Name) || - !plan.Description.Equal(state.Description) || - !plan.ComplexArgument.Equal(state.ComplexArgument) || + if !plan.Description.Equal(state.Description) || + !plan.TLSInspectionConfiguration.Equal(state.TLSInspectionConfiguration) || + !plan.EncryptionConfiguration.Equal(state.EncryptionConfiguration) || !plan.Type.Equal(state.Type) { in := &networkfirewall.UpdateTLSInspectionConfigurationInput{ // TIP: Mandatory or fields that will always be present can be set when // you create the Input structure. (Replace these with real fields.) - TLSInspectionConfigurationId: aws.String(plan.ID.ValueString()), + TLSInspectionConfigurationArn: aws.String(plan.ARN.ValueString()), TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), - TLSInspectionConfigurationType: aws.String(plan.Type.ValueString()), + UpdateToken: aws.String(plan.UpdateToken.ValueString()), } if !plan.Description.IsNull() { @@ -533,20 +533,39 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res // used. in.Description = aws.String(plan.Description.ValueString()) } - if !plan.ComplexArgument.IsNull() { - // TIP: Use an expander to assign a complex argument. The elements must be - // deserialized into the appropriate struct before being passed to the expander. - var tfList []complexArgumentData - resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) + // if !plan.ComplexArgument.IsNull() { + // // TIP: Use an expander to assign a complex argument. The elements must be + // // deserialized into the appropriate struct before being passed to the expander. + // var tfList []complexArgumentData + // resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) + // if resp.Diagnostics.HasError() { + // return + // } + + // in.ComplexArgument = expandComplexArgument(tfList) + // } + + if !plan.TLSInspectionConfiguration.IsNull() { + var tfList []tlsInspectionConfigurationData + resp.Diagnostics.Append(plan.TLSInspectionConfiguration.ElementsAs(ctx, &tfList, false)...) if resp.Diagnostics.HasError() { return } - - in.ComplexArgument = expandComplexArgument(tfList) + in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(tfList) + } + if !plan.EncryptionConfiguration.IsNull() { + var tfList []encryptionConfigurationData + resp.Diagnostics.Append(plan.EncryptionConfiguration.ElementsAs(ctx, &tfList, false)...) + if resp.Diagnostics.HasError() { + return + } + in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) + } + // TIP: -- 4. Call the AWS modify/update function - out, err := conn.UpdateTLSInspectionConfiguration(ctx, in) + out, err := conn.UpdateTLSInspectionConfigurationWithContext(ctx, in) if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionUpdating, ResNameTLSInspectionConfiguration, plan.ID.String(), err), @@ -554,7 +573,7 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res ) return } - if out == nil || out.TLSInspectionConfiguration == nil { + if out == nil || out.TLSInspectionConfigurationResponse == nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionUpdating, ResNameTLSInspectionConfiguration, plan.ID.String(), nil), errors.New("empty output").Error(), @@ -563,8 +582,13 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res } // TIP: Using the output from the update function, re-set any computed attributes - plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfiguration.Arn) - plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfiguration.TLSInspectionConfigurationId) + plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) + plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) + + plan.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) + plan.NumberOfAssociations = flex.Int64ToFramework(ctx, out.TLSInspectionConfigurationResponse.NumberOfAssociations) + plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) + plan.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) } @@ -807,7 +831,7 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: certificateAttrTypes} + elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} if len(certificateList) == 0 { return types.ListNull(elemType), diags @@ -831,7 +855,7 @@ func flattenCertificates(ctx context.Context, certificateList []*networkfirewall func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: certificateAttrTypes} + elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} if certificate == nil { return types.ListNull(elemType), diags @@ -843,7 +867,7 @@ func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.Tls "status": flex.StringToFramework(ctx, certificate.Status), "status_message": flex.StringToFramework(ctx, certificate.StatusMessage), } - objVal, d := types.ObjectValue(certificateAttrTypes, obj) + objVal, d := types.ObjectValue(certificatesAttrTypes, obj) diags.Append(d...) listVal, d := types.ListValue(elemType, []attr.Value{objVal}) @@ -1018,34 +1042,55 @@ func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfigurat // // See more: // https://hashicorp.github.io/terraform-provider-aws/data-handling-and-conversion/ -func expandComplexArgument(tfList []complexArgumentData) *awstypes.ComplexArgument { +// func expandComplexArgument(tfList []complexArgumentData) *awstypes.ComplexArgument { +// if len(tfList) == 0 { +// return nil +// } + +// tfObj := tfList[0] +// apiObject := &awstypes.ComplexArgument{ +// NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), +// } +// if !tfObj.NestedOptional.IsNull() { +// apiObject.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) +// } + +// return apiObject +// } + +// TODO: add note explaining why not using existing expandEncryptionConfiguration() +func expandTLSEncryptionConfiguration(tfList []encryptionConfigurationData) *networkfirewall.EncryptionConfiguration { if len(tfList) == 0 { return nil } tfObj := tfList[0] - apiObject := &awstypes.ComplexArgument{ - NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), - } - if !tfObj.NestedOptional.IsNull() { - apiObject.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) + apiObject := &networkfirewall.EncryptionConfiguration{ + KeyId: aws.String(tfObj.KeyId.ValueString()), + Type: aws.String(tfObj.Type.ValueString()), } return apiObject } -func expandTLSInspectionConfiguration(tfList []tlsInspectionConfigurationData) []networkfirewall.TLSInspectionConfiguration { - var apiObject []networkfirewall.TLSInspectionConfiguration +func expandTLSInspectionConfiguration(tfList []tlsInspectionConfigurationData) *networkfirewall.TLSInspectionConfiguration { + if len(tfList) == 0 { + return nil + } + + // var apiObject []networkfirewall.TLSInspectionConfiguration - for _, item := range tfList { - conf := networkfirewall.TLSInspectionConfiguration{} - if !item.ServerCertificateConfiguration.IsNull() { - var serverConfig []serverCertificateConfigurationsData - conf.ServerCertificateConfigurations = expandServerCertificateConfigurations(serverConfig) - } - - apiObject = append(apiObject, conf) + tfObj := tfList[0] + + // for _, item := range tfList { + apiObject := &networkfirewall.TLSInspectionConfiguration{} + if !tfObj.ServerCertificateConfiguration.IsNull() { + var serverConfig []serverCertificateConfigurationsData + apiObject.ServerCertificateConfigurations = expandServerCertificateConfigurations(serverConfig) } + + // apiObject = append(apiObject, conf) + return apiObject } @@ -1105,7 +1150,7 @@ func expandScopes(tfList []scopeData) []*networkfirewall.ServerCertificateScope for _, tfObj := range tfList { item := &networkfirewall.ServerCertificateScope{ - // Protocols: + // Protocols: aws.Int64Slice(), } if !tfObj.DestinationPorts.IsNull() { var destinationPorts []portRangeData @@ -1162,40 +1207,40 @@ func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall // TIP: Even when you have a list with max length of 1, this plural function // works brilliantly. However, if the AWS API takes a structure rather than a // slice of structures, you will not need it. -func expandComplexArguments(tfList []complexArgumentData) []*networkfirewall.ComplexArgument { - // TIP: The AWS API can be picky about whether you send a nil or zero- - // length for an argument that should be cleared. For example, in some - // cases, if you send a nil value, the AWS API interprets that as "make no - // changes" when what you want to say is "remove everything." Sometimes - // using a zero-length list will cause an error. - // - // As a result, here are two options. Usually, option 1, nil, will work as - // expected, clearing the field. But, test going from something to nothing - // to make sure it works. If not, try the second option. - // TIP: Option 1: Returning nil for zero-length list - if len(tfList) == 0 { - return nil - } - var apiObject []*awstypes.ComplexArgument - // TIP: Option 2: Return zero-length list for zero-length list. If option 1 does - // not work, after testing going from something to nothing (if that is - // possible), uncomment out the next line and remove option 1. - // - // apiObject := make([]*networkfirewall.ComplexArgument, 0) - - for _, tfObj := range tfList { - item := &networkfirewall.ComplexArgument{ - NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), - } - if !tfObj.NestedOptional.IsNull() { - item.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) - } +// func expandComplexArguments(tfList []complexArgumentData) []*networkfirewall.ComplexArgument { +// // TIP: The AWS API can be picky about whether you send a nil or zero- +// // length for an argument that should be cleared. For example, in some +// // cases, if you send a nil value, the AWS API interprets that as "make no +// // changes" when what you want to say is "remove everything." Sometimes +// // using a zero-length list will cause an error. +// // +// // As a result, here are two options. Usually, option 1, nil, will work as +// // expected, clearing the field. But, test going from something to nothing +// // to make sure it works. If not, try the second option. +// // TIP: Option 1: Returning nil for zero-length list +// if len(tfList) == 0 { +// return nil +// } +// var apiObject []*awstypes.ComplexArgument +// // TIP: Option 2: Return zero-length list for zero-length list. If option 1 does +// // not work, after testing going from something to nothing (if that is +// // possible), uncomment out the next line and remove option 1. +// // +// // apiObject := make([]*networkfirewall.ComplexArgument, 0) + +// for _, tfObj := range tfList { +// item := &networkfirewall.ComplexArgument{ +// NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), +// } +// if !tfObj.NestedOptional.IsNull() { +// item.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) +// } - apiObject = append(apiObject, item) - } +// apiObject = append(apiObject, item) +// } - return apiObject -} +// return apiObject +// } // TIP: ==== DATA STRUCTURES ==== // With Terraform Plugin-Framework configurations are deserialized into From e5d6930652e9f1c9ec97c519fa04e3293190a1c1 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:40:44 -0500 Subject: [PATCH 05/68] [WIP] Begin building acceptance tests --- .../tls_inspection_configuration.go | 12 +- .../tls_inspection_configuration_test.go | 168 +++++++++++------- 2 files changed, 109 insertions(+), 71 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index d627a84bc2e..da32d399c24 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -21,7 +21,7 @@ import ( "github.com/aws/aws-sdk-go/service/networkfirewall" awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" - "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + // "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" @@ -29,7 +29,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" + // "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/create" @@ -203,7 +203,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, - "scopes": schema.ListNestedBlock{ + "scope": schema.ListNestedBlock{ NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "protocols": schema.ListAttribute{ @@ -1105,7 +1105,7 @@ func expandServerCertificateConfigurations(tfList []serverCertificateConfigurati var certificateRevocationStatus []checkCertificateRevocationStatusData conf.CheckCertificateRevocationStatus = expandCheckCertificateRevocationStatus(certificateRevocationStatus) } - if !item.Scopes.IsNull() { + if !item.Scope.IsNull() { var scopesList []scopeData conf.Scopes = expandScopes(scopesList) } @@ -1291,7 +1291,7 @@ type tlsInspectionConfigurationData struct { type serverCertificateConfigurationsData struct { CertificateAuthorityArn types.String `tfsdk:"certificate_authority_arn"` CheckCertificateRevocationsStatus types.List `tfsdk:"check_certificate_revocations_status"` - Scopes types.List `tfsdk:"scopes"` + Scope types.List `tfsdk:"scope"` ServerCertificates types.List `tfsdk:"server_certificates"` } @@ -1352,7 +1352,7 @@ var tlsInspectionConfigurationAttrTypes = map[string]attr.Type{ var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ "certificate_authority_arn": types.StringType, "check_certificate_revocations_status": types.ListType{ElemType: types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes}}, - "scopes": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, + "scope": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, "server_certificates": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificatesAttrTypes}}, } diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 00660a412b0..cbf28a4cf23 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -2,22 +2,6 @@ // SPDX-License-Identifier: MPL-2.0 package networkfirewall_test -// **PLEASE DELETE THIS AND ALL TIP COMMENTS BEFORE SUBMITTING A PR FOR REVIEW!** -// -// TIP: ==== INTRODUCTION ==== -// Thank you for trying the skaff tool! -// -// You have opted to include these helpful comments. They all include "TIP:" -// to help you find and remove them when you're done with them. -// -// While some aspects of this file are customized to your input, the -// scaffold tool does *not* look at the AWS API and ensure it has correct -// function, structure, and variable names. It makes guesses based on -// commonalities. You will need to make significant adjustments. -// -// In other words, as generated, this is a rough outline of the work you will -// need to do. If something doesn't make sense for your situation, get rid of -// it. import ( // TIP: ==== IMPORTS ==== @@ -37,10 +21,9 @@ import ( "fmt" "testing" - "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/networkfirewall" "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" + "github.com/aws/aws-sdk-go/service/networkfirewall" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -148,17 +131,17 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { t.Skip("skipping long-running test in short mode") } - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationResponse + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_tls_inspection_configuration.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, names.NetworkFirewallEndpointID) + acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewallEndpointID), + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ @@ -166,15 +149,15 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { Config: testAccTLSInspectionConfigurationConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), - resource.TestCheckResourceAttrSet(resourceName, "maintenance_window_start_time.0.day_of_week"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "user.*", map[string]string{ - "console_access": "false", - "groups.#": "0", - "username": "Test", - "password": "TestTest1234", - }), - acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "networkfirewall", regexache.MustCompile(`tlsinspectionconfiguration:+.`)), + // resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), + // resource.TestCheckResourceAttrSet(resourceName, "maintenance_window_start_time.0.day_of_week"), + // resource.TestCheckTypeSetElemNestedAttrs(resourceName, "user.*", map[string]string{ + // "console_access": "false", + // "groups.#": "0", + // "username": "Test", + // "password": "TestTest1234", + // }), + // acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "networkfirewall", regexache.MustCompile(`tlsinspectionconfiguration:+.`)), ), }, { @@ -240,11 +223,11 @@ func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource _, err := conn.DescribeTLSInspectionConfiguration(ctx, &networkfirewall.DescribeTLSInspectionConfigurationInput{ TLSInspectionConfigurationId: aws.String(rs.Primary.ID), }) - if errs.IsA[*types.ResourceNotFoundException](err){ + if errs.IsA[*types.ResourceNotFoundException](err) { return nil } if err != nil { - return create.Error(names.NetworkFirewall, create.ErrActionCheckingDestroyed, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, err) + return create.Error(names.NetworkFirewall, create.ErrActionCheckingDestroyed, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, err) } return create.Error(names.NetworkFirewall, create.ErrActionCheckingDestroyed, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, errors.New("not destroyed")) @@ -254,7 +237,7 @@ func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource } } -func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name string, tlsinspectionconfiguration *networkfirewall.DescribeTLSInspectionConfigurationResponse) resource.TestCheckFunc { +func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name string, tlsinspectionconfiguration *networkfirewall.DescribeTLSInspectionConfigurationOutput) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[name] if !ok { @@ -265,9 +248,9 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name stri return create.Error(names.NetworkFirewall, create.ErrActionCheckingExistence, tfnetworkfirewall.ResNameTLSInspectionConfiguration, name, errors.New("not set")) } - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) - resp, err := conn.DescribeTLSInspectionConfiguration(ctx, &networkfirewall.DescribeTLSInspectionConfigurationInput{ - TLSInspectionConfigurationId: aws.String(rs.Primary.ID), + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + resp, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, &networkfirewall.DescribeTLSInspectionConfigurationInput{ + TLSInspectionConfigurationArn: aws.String(rs.Primary.Attributes["arn"]), }) if err != nil { @@ -280,19 +263,19 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name stri } } -func testAccPreCheck(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) +// func testAccPreCheck(ctx context.Context, t *testing.T) { +// conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) - input := &networkfirewall.ListTLSInspectionConfigurationsInput{} - _, err := conn.ListTLSInspectionConfigurations(ctx, input) +// input := &networkfirewall.ListTLSInspectionConfigurationsInput{} +// _, err := conn.ListTLSInspectionConfigurationsWithContext(ctx, input) - if acctest.PreCheckSkipError(err) { - t.Skipf("skipping acceptance testing: %s", err) - } - if err != nil { - t.Fatalf("unexpected PreCheck error: %s", err) - } -} +// if acctest.PreCheckSkipError(err) { +// t.Skipf("skipping acceptance testing: %s", err) +// } +// if err != nil { +// t.Fatalf("unexpected PreCheck error: %s", err) +// } +// } func testAccCheckTLSInspectionConfigurationNotRecreated(before, after *networkfirewall.DescribeTLSInspectionConfigurationResponse) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -304,29 +287,84 @@ func testAccCheckTLSInspectionConfigurationNotRecreated(before, after *networkfi } } -func testAccTLSInspectionConfigurationConfig_basic(rName, version string) string { +func testAccTLSInspectionConfigurationConfig_basic(rName string) string { return fmt.Sprintf(` -resource "aws_security_group" "test" { +resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = + check_certificate_revocation_status { + revoked_status_action = "PASS" + unknown_status_action = "PASS" + } + server_certificates { + resource_arn = + } + scopes { + protocols = [ 6 ] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +`, rName) } -resource "aws_networkfirewall_tls_inspection_configuration" "test" { - tls_inspection_configuration_name = %[1]q - engine_type = "ActiveNetworkFirewall" - engine_version = %[2]q - host_instance_type = "networkfirewall.t2.micro" - security_groups = [aws_security_group.test.id] - authentication_strategy = "simple" - storage_type = "efs" - - logs { - general = true +func testAccTLSInspectionConfigurationConfig_withEncryptionConfiguration(rName string) string { + return fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = "test" + deletion_window_in_days = 10 } - user { - username = "Test" - password = "TestTest1234" - } +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + description = "test" + encryption_configuration { + key_id = aws_kms_key.test.key_id + type = "CUSTOMER_KMS" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = + check_certificate_revocation_status { + revoked_status_action = "PASS" + unknown_status_action = "PASS" + } + server_certificates { + resource_arn = + } + scopes { + protocols = [ 6 ] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } -`, rName, version) +`, rName) } From 8477fb6831ac3767712f33a6e418ad924dd5ff90 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:53:51 -0500 Subject: [PATCH 06/68] Run make gen --- internal/service/networkfirewall/service_package_gen.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 3b7562c45b4..eb8b8184fea 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -20,7 +20,12 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourceTLSInspectionConfiguration, + Name: "TLS Inspection Configuration", + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { From a9c818b26c3f8f2b2a6a3ffc8eea5e4c80d8172b Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:10:23 -0500 Subject: [PATCH 07/68] [WIP] Additional flex functions --- .../tls_inspection_configuration.go | 177 ++++++++++++++++-- 1 file changed, 163 insertions(+), 14 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index da32d399c24..ed441fd91ca 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -472,6 +472,10 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou certificates, d := flattenCertificates(ctx, out.TLSInspectionConfigurationResponse.Certificates) resp.Diagnostics.Append(d...) state.Certificates = certificates + + tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) + resp.Diagnostics.Append(d...) + state.TLSInspectionConfiguration = tlsInspectionConfiguration // TIP: Setting a complex type. // complexArgument, d := flattenComplexArgument(ctx, out.ComplexArgument) @@ -828,6 +832,115 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo // return listVal, diags // } +func flattenTLSInspectionConfiguration(ctx context.Context, apiObject *networkfirewall.TLSInspectionConfiguration)(types.List, diag.Diagnostics){ + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: tlsInspectionConfigurationAttrTypes} + + if apiObject == nil { + return types.ListNull(elemType), diags + } + + serverCertConfig, d := flattenServerCertificateConfigurations(ctx, apiObject.ServerCertificateConfigurations) + diags.Append(d...) + + obj := map[string]attr.Value{ + "server_certificate_configurations": serverCertConfig, + } + objVal, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) + diags.Append(d...) + + listVal, d := types.ListValue(elemType, []attr.Value{objVal}) + diags.Append(d...) + + return listVal, diags + +} + +func flattenServerCertificateConfigurations(ctx context.Context, serverCertificateConfigurations []*networkfirewall.ServerCertificateConfiguration)(types.List, diag.Diagnostics){ + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes} + + if len(serverCertificateConfigurations) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, serverCertificateConfiguration := range serverCertificateConfigurations { + checkCertRevocationStatus, d := flattenCheckCertificateRevocationStatus(ctx, serverCertificateConfiguration.CheckCertificateRevocationStatus) + diags.Append(d...) + scopes, d := flattenScopes(ctx, serverCertificateConfiguration.Scopes) + diags.Append(d...) + serverCertificates, d := flattenServerCertificates(ctx, serverCertificateConfiguration.ServerCertificates) + diags.Append(d...) + + obj := map[string]attr.Value{ + "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), + "check_certificate_revocation_status": checkCertRevocationStatus, + "scopes": scopes, + "server_certificates": serverCertificates, + } + + flattenedServerCertificateConfiguration, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) + diags.Append(d...) + elems = append(elems, flattenedServerCertificateConfiguration) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags +} + +func flattenCheckCertificateRevocationStatus(ctx context.Context, checkCertificateRevocationStatus *networkfirewall.CheckCertificateRevocationStatusActions)(types.List, diag.Diagnostics){ + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes} + + if checkCertificateRevocationStatus == nil { + return types.ListNull(elemType), diags + } + + obj := map[string]attr.Value{ + "revoked_status_action": flex.StringToFramework(ctx, checkCertificateRevocationStatus.RevokedStatusAction), + "unknown_status_action": flex.StringToFramework(ctx, checkCertificateRevocationStatus.UnknownStatusAction), + } + + flattenedCheckCertificateRevocationStatus, d := types.ObjectValue(checkCertificateRevocationStatusAttrTypes, obj) + diags.Append(d...) + + listVal, d := types.ListValue(elemType, []attr.Value{flattenedCheckCertificateRevocationStatus}) + diags.Append(d...) + + return listVal, diags +} + +func flattenServerCertificates(ctx context.Context, serverCertificateList []*networkfirewall.ServerCertificate) (types.List, diag.Diagnostics) { + var diags diag.Diagnostics + elemType := types.ObjectType{AttrTypes: serverCertificatesAttrTypes} + + if len(serverCertificateList) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, serverCertificate := range serverCertificateList { + if serverCertificate == nil { + continue + } + obj := map[string]attr.Value{ + "resource_arn": flex.StringToFramework(ctx, serverCertificate.ResourceArn), + } + + flattenedServerCertificate, d:= types.ObjectValue(serverCertificatesAttrTypes, obj) + + diags.Append(d...) + elems = append(elems, flattenedServerCertificate) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags +} func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ var diags diag.Diagnostics @@ -893,15 +1006,21 @@ func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertific } destinationPorts, d := flattenPortRange(ctx, scope.DestinationPorts) + diags.Append(d...) destinations, d := flattenSourceDestinations(ctx, scope.Destinations) + diags.Append(d...) + protocols, d := flattenProtocols(ctx, scope.Protocols) + diags.Append(d...) sourcePorts, d := flattenPortRange(ctx, scope.SourcePorts) + diags.Append(d...) sources, d := flattenSourceDestinations(ctx, scope.Sources) + diags.Append(d...) obj := map[string]attr.Value{ "destination_ports": destinationPorts, "destinations": destinations, - // "protocols": flex. + "protocols": protocols, "source_ports": sourcePorts, "sources": sources, } @@ -918,6 +1037,30 @@ func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertific } +func flattenProtocols(ctx context.Context, list []*int64)(types.List, diag.Diagnostics){ + var diags diag.Diagnostics + elemType := types.Int64Type + + if len(list) == 0 { + return types.ListNull(elemType), diags + } + + elems := []attr.Value{} + for _, item := range list { + if item == nil { + continue + } + + objVal := types.Int64Value(*item) + + elems = append(elems, objVal) + } + + listVal, d := types.ListValue(elemType, elems) + diags.Append(d...) + + return listVal, diags +} func flattenSourceDestinations(ctx context.Context, destinations []*networkfirewall.Address) (types.List, diag.Diagnostics) { var diags diag.Diagnostics @@ -978,8 +1121,6 @@ func flattenPortRange(ctx context.Context, ranges []*networkfirewall.PortRange) return listVal, diags } -func flattenCheckCertificateRevocationStatus(){} - func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfiguration *networkfirewall.EncryptionConfiguration) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: encryptionConfigurationAttrTypes} @@ -1201,7 +1342,15 @@ func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall return apiObject } - +// func expandTLSCertificateData(tfObj certificatesData) *networkfirewall.TlsCertificateData { +// item := &networkfirewall.TlsCertificateData{ +// CertificateArn: aws.String(tfObj.CertificateArn.ValueString()), +// CertificateSerial: aws.String(tfObj.CertificateSerial.ValueString()), +// Status: aws.String(tfObj.Status.ValueString()), +// StatusMessage: aws.String(tfObj.StatusMessage.ValueString()), +// } +// return item +// } // TIP: Even when you have a list with max length of 1, this plural function @@ -1277,12 +1426,12 @@ type encryptionConfigurationData struct { KeyId types.String `tfsdk:"key_id"` } -type certificatesData struct { - CertificateArn types.String `tfsdk:"certificate_arn"` - CertificateSerial types.String `tfsdk:"certificate_serial"` - Status types.String `tfsdk:"status"` - StatusMessage types.String `tfsdk:"status_message"` -} +// type certificatesData struct { +// CertificateArn types.String `tfsdk:"certificate_arn"` +// CertificateSerial types.String `tfsdk:"certificate_serial"` +// Status types.String `tfsdk:"status"` +// StatusMessage types.String `tfsdk:"status_message"` +// } type tlsInspectionConfigurationData struct { ServerCertificateConfiguration types.List `tfsdk:"server_certificate_configuration"` @@ -1295,10 +1444,10 @@ type serverCertificateConfigurationsData struct { ServerCertificates types.List `tfsdk:"server_certificates"` } -type complexArgumentData struct { - NestedRequired types.String `tfsdk:"nested_required"` - NestedOptional types.String `tfsdk:"nested_optional"` -} +// type complexArgumentData struct { +// NestedRequired types.String `tfsdk:"nested_required"` +// NestedOptional types.String `tfsdk:"nested_optional"` +// } type scopeData struct { DestinationPorts types.List `tfsdk:"destination_ports"` From b1dcb5a4e7158938c164e362532a41df462c2102 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:38:06 -0500 Subject: [PATCH 08/68] [WIP] Acceptance tests and flex fixes --- .../service/networkfirewall/exports_test.go | 8 + .../tls_inspection_configuration.go | 355 ++++++++++-------- .../tls_inspection_configuration_test.go | 280 +++++++------- 3 files changed, 360 insertions(+), 283 deletions(-) create mode 100644 internal/service/networkfirewall/exports_test.go diff --git a/internal/service/networkfirewall/exports_test.go b/internal/service/networkfirewall/exports_test.go new file mode 100644 index 00000000000..f488ce5682d --- /dev/null +++ b/internal/service/networkfirewall/exports_test.go @@ -0,0 +1,8 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package networkfirewall + +var ( + ResourceTLSInspectionConfiguration = newResourceTLSInspectionConfiguration +) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index ed441fd91ca..9356d369baf 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -15,12 +15,14 @@ import ( // awstypes.. "context" "errors" + "fmt" "time" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" + "github.com/aws/aws-sdk-go/service/networkfirewall" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + // "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" @@ -29,6 +31,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + // "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" @@ -39,6 +42,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) + // TIP: ==== FILE STRUCTURE ==== // All resources should follow this basic outline. Improve this resource's // maintainability by sticking to it. @@ -53,7 +57,7 @@ import ( // @FrameworkResource(name="TLS Inspection Configuration") func newResourceTLSInspectionConfiguration(_ context.Context) (resource.ResourceWithConfigure, error) { r := &resourceTLSInspectionConfiguration{} - + // TIP: ==== CONFIGURABLE TIMEOUTS ==== // Users can configure timeout lengths but you need to use the times they // provide. Access the timeout they configure (or the defaults) using, @@ -88,28 +92,31 @@ func (r *resourceTLSInspectionConfiguration) Metadata(_ context.Context, req res // * Do not add a blank line between attributes. // // Attribute basics: -// * If a user can provide a value ("configure a value") for an -// attribute (e.g., instances = 5), we call the attribute an -// "argument." -// * You change the way users interact with attributes using: -// - Required -// - Optional -// - Computed -// * There are only four valid combinations: +// - If a user can provide a value ("configure a value") for an +// attribute (e.g., instances = 5), we call the attribute an +// "argument." +// - You change the way users interact with attributes using: +// - Required +// - Optional +// - Computed +// - There are only four valid combinations: // // 1. Required only - the user must provide a value // Required: true, // -// 2. Optional only - the user can configure or omit a value; do not -// use Default or DefaultFunc +// 2. Optional only - the user can configure or omit a value; do not +// use Default or DefaultFunc +// // Optional: true, // -// 3. Computed only - the provider can provide a value but the user -// cannot, i.e., read-only +// 3. Computed only - the provider can provide a value but the user +// cannot, i.e., read-only +// // Computed: true, // -// 4. Optional AND Computed - the provider or user can provide a value; -// use this combination if you are using Default +// 4. Optional AND Computed - the provider or user can provide a value; +// use this combination if you are using Default +// // Optional: true, // Computed: true, // @@ -134,8 +141,8 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res // TIP: ==== PLAN MODIFIERS ==== // Plan modifiers were introduced with Plugin-Framework to provide a mechanism // for adjusting planned changes prior to apply. The planmodifier subpackage - // provides built-in modifiers for many common use cases such as - // requiring replacement on a value change ("ForceNew: true" in Plugin-SDK + // provides built-in modifiers for many common use cases such as + // requiring replacement on a value change ("ForceNew: true" in Plugin-SDK // resources). // // See more: @@ -158,6 +165,42 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, Blocks: map[string]schema.Block{ + "certificate_authority": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "certificate_arn": schema.StringAttribute{ + Computed: true, + }, + "certificate_serial": schema.StringAttribute{ + Computed: true, + }, + "status": schema.StringAttribute{ + Computed: true, + }, + "status_message": schema.StringAttribute{ + Computed: true, + }, + }, + }, + }, + "certificates": schema.ListNestedBlock{ + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "certificate_arn": schema.StringAttribute{ + Computed: true, + }, + "certificate_serial": schema.StringAttribute{ + Computed: true, + }, + "status": schema.StringAttribute{ + Computed: true, + }, + "status_message": schema.StringAttribute{ + Computed: true, + }, + }, + }, + }, "encryption_configuration": schema.ListNestedBlock{ NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ @@ -177,7 +220,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "certificate_authority_arn": schema.StringAttribute{ - Required: true, + Optional: true, }, }, Blocks: map[string]schema.Block{ @@ -257,20 +300,20 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, - }, }, }, }, + }, }, }, // "complex_argument": schema.ListNestedBlock{ // // TIP: ==== LIST VALIDATORS ==== - // // List and set validators take the place of MaxItems and MinItems in + // // List and set validators take the place of MaxItems and MinItems in // // Plugin-Framework based resources. Use listvalidator.SizeAtLeast(1) to - // // make a nested object required. Similar to Plugin-SDK, complex objects + // // make a nested object required. Similar to Plugin-SDK, complex objects // // can be represented as lists or sets with listvalidator.SizeAtMost(1). // // - // // For a complete mapping of Plugin-SDK to Plugin-Framework schema fields, + // // For a complete mapping of Plugin-SDK to Plugin-Framework schema fields, // // see: // // https://developer.hashicorp.com/terraform/plugin/framework/migrating/attributes-blocks/blocks // Validators: []validator.List{ @@ -289,7 +332,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res // }, // }, // }, - // }, + // }, "timeouts": timeouts.Block(ctx, timeouts.Opts{ Create: true, Update: true, @@ -310,20 +353,20 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res // 4. Call the AWS create/put function // 5. Using the output from the create function, set the minimum arguments // and attributes for the Read function to work, as well as any computed - // only attributes. + // only attributes. // 6. Use a waiter to wait for create to complete // 7. Save the request plan to response state // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - + // TIP: -- 2. Fetch the plan var plan resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) if resp.Diagnostics.HasError() { return } - + // TIP: -- 3. Populate a create input structure in := &networkfirewall.CreateTLSInspectionConfigurationInput{ // NOTE: Name is mandatory @@ -346,7 +389,7 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res } // in.TLSInspectionConfiguration = expandComplexArgument(tfList) - in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(tfList) + in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(ctx, tfList) } if !plan.EncryptionConfiguration.IsNull() { @@ -360,7 +403,7 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) } - + // TIP: -- 4. Call the AWS create function out, err := conn.CreateTLSInspectionConfiguration(in) if err != nil { @@ -379,12 +422,12 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res ) return } - + // TIP: -- 5. Using the output from the create function, set the minimum attributes // Output consists only of TLSInspectionConfigurationResponse plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) - + // TIP: -- 6. Use a waiter to wait for create to complete createTimeout := r.CreateTimeout(ctx, plan.Timeouts) _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ID.ValueString(), createTimeout) @@ -395,7 +438,7 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res ) return } - + // TIP: -- 7. Save the request plan to response state resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) } @@ -414,14 +457,14 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - + // TIP: -- 2. Fetch the state var state resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { return } - + // TIP: -- 3. Get the resource from AWS using an API Get, List, or Describe- // type function, or, better yet, using a finder. out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, state.ARN.ValueString()) @@ -437,24 +480,24 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou ) return } - + // TIP: -- 5. Set the arguments and attributes // // For simple data types (i.e., schema.StringAttribute, schema.BoolAttribute, - // schema.Int64Attribute, and schema.Float64Attribue), simply setting the + // schema.Int64Attribute, and schema.Float64Attribue), simply setting the // appropriate data struct field is sufficient. The flex package implements - // helpers for converting between Go and Plugin-Framework types seamlessly. No + // helpers for converting between Go and Plugin-Framework types seamlessly. No // error or nil checking is necessary. // // However, there are some situations where more handling is needed such as - // complex data types (e.g., schema.ListAttribute, schema.SetAttribute). In + // complex data types (e.g., schema.ListAttribute, schema.SetAttribute). In // these cases the flatten function may have a diagnostics return value, which // should be appended to resp.Diagnostics. state.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) state.Description = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.Description) state.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) state.Name = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationName) - + state.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) state.NumberOfAssociations = flex.Int64ToFramework(ctx, out.TLSInspectionConfigurationResponse.NumberOfAssociations) state.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) @@ -464,11 +507,11 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou encryptionConfiguration, d := flattenTLSEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) resp.Diagnostics.Append(d...) state.EncryptionConfiguration = encryptionConfiguration - + certificateAuthority, d := flattenTLSCertificate(ctx, out.TLSInspectionConfigurationResponse.CertificateAuthority) resp.Diagnostics.Append(d...) state.CertificateAuthority = certificateAuthority - + certificates, d := flattenCertificates(ctx, out.TLSInspectionConfigurationResponse.Certificates) resp.Diagnostics.Append(d...) state.Certificates = certificates @@ -476,12 +519,12 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) resp.Diagnostics.Append(d...) state.TLSInspectionConfiguration = tlsInspectionConfiguration - + // TIP: Setting a complex type. // complexArgument, d := flattenComplexArgument(ctx, out.ComplexArgument) // resp.Diagnostics.Append(d...) // state.ComplexArgument = complexArgument - + // TIP: -- 6. Set the state resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } @@ -509,7 +552,7 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res // 6. Save the request plan to response state // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - + // TIP: -- 2. Fetch the plan var plan, state resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) @@ -517,19 +560,18 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res if resp.Diagnostics.HasError() { return } - + // TIP: -- 3. Populate a modify input structure and check for changes if !plan.Description.Equal(state.Description) || !plan.TLSInspectionConfiguration.Equal(state.TLSInspectionConfiguration) || - !plan.EncryptionConfiguration.Equal(state.EncryptionConfiguration) || - !plan.Type.Equal(state.Type) { + !plan.EncryptionConfiguration.Equal(state.EncryptionConfiguration) { in := &networkfirewall.UpdateTLSInspectionConfigurationInput{ // TIP: Mandatory or fields that will always be present can be set when // you create the Input structure. (Replace these with real fields.) - TLSInspectionConfigurationArn: aws.String(plan.ARN.ValueString()), + TLSInspectionConfigurationArn: aws.String(plan.ARN.ValueString()), TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), - UpdateToken: aws.String(plan.UpdateToken.ValueString()), + UpdateToken: aws.String(plan.UpdateToken.ValueString()), } if !plan.Description.IsNull() { @@ -555,10 +597,10 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res if resp.Diagnostics.HasError() { return } - in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(tfList) - + in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(ctx, tfList) + } - + if !plan.EncryptionConfiguration.IsNull() { var tfList []encryptionConfigurationData resp.Diagnostics.Append(plan.EncryptionConfiguration.ElementsAs(ctx, &tfList, false)...) @@ -584,7 +626,7 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res ) return } - + // TIP: Using the output from the update function, re-set any computed attributes plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) @@ -595,7 +637,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res plan.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) } - // TIP: -- 5. Use a waiter to wait for update to complete updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) _, err := waitTLSInspectionConfigurationUpdated(ctx, conn, plan.ID.ValueString(), updateTimeout) @@ -607,7 +648,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res return } - // TIP: -- 6. Save the request plan to response state resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) } @@ -615,19 +655,19 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - + // TIP: -- 2. Fetch the state var state resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { return } - + // TIP: -- 3. Populate a delete input structure in := &networkfirewall.DeleteTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(state.ARN.ValueString()), } - + // TIP: -- 4. Call the AWS delete function _, err := conn.DeleteTLSInspectionConfigurationWithContext(ctx, in) // TIP: On rare occassions, the API returns a not found error after deleting a @@ -642,7 +682,7 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res ) return } - + // TIP: -- 5. Use a waiter to wait for delete to complete deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) _, err = waitTLSInspectionConfigurationDeleted(ctx, conn, state.ID.ValueString(), deleteTimeout) @@ -666,7 +706,6 @@ func (r *resourceTLSInspectionConfiguration) ImportState(ctx context.Context, re resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } - // TIP: ==== STATUS CONSTANTS ==== // Create constants for states and statuses if the service does not // already have suitable constants. We prefer that you use the constants @@ -735,10 +774,10 @@ func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfir // be additional pending states, however. func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, id string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{statusDeleting, statusNormal}, - Target: []string{}, - Refresh: statusTLSInspectionConfiguration(ctx, conn, id), - Timeout: timeout, + Pending: []string{statusDeleting, statusNormal}, + Target: []string{}, + Refresh: statusTLSInspectionConfiguration(ctx, conn, id), + Timeout: timeout, } outputRaw, err := stateConf.WaitForStateContext(ctx) @@ -780,7 +819,7 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo in := &networkfirewall.DescribeTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(arn), } - + out, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, in) if err != nil { if errs.IsA[*awstypes.ResourceNotFoundException](err) { @@ -802,7 +841,7 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo // TIP: ==== FLEX ==== // Flatteners and expanders ("flex" functions) help handle complex data -// types. Flatteners take an API data type and return the equivalent Plugin-Framework +// types. Flatteners take an API data type and return the equivalent Plugin-Framework // type. In other words, flatteners translate from AWS -> Terraform. // // On the other hand, expanders take a Terraform data structure and return @@ -832,7 +871,7 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo // return listVal, diags // } -func flattenTLSInspectionConfiguration(ctx context.Context, apiObject *networkfirewall.TLSInspectionConfiguration)(types.List, diag.Diagnostics){ +func flattenTLSInspectionConfiguration(ctx context.Context, apiObject *networkfirewall.TLSInspectionConfiguration) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: tlsInspectionConfigurationAttrTypes} @@ -856,7 +895,7 @@ func flattenTLSInspectionConfiguration(ctx context.Context, apiObject *networkfi } -func flattenServerCertificateConfigurations(ctx context.Context, serverCertificateConfigurations []*networkfirewall.ServerCertificateConfiguration)(types.List, diag.Diagnostics){ +func flattenServerCertificateConfigurations(ctx context.Context, serverCertificateConfigurations []*networkfirewall.ServerCertificateConfiguration) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes} @@ -874,10 +913,10 @@ func flattenServerCertificateConfigurations(ctx context.Context, serverCertifica diags.Append(d...) obj := map[string]attr.Value{ - "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), + "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), "check_certificate_revocation_status": checkCertRevocationStatus, - "scopes": scopes, - "server_certificates": serverCertificates, + "scopes": scopes, + "server_certificates": serverCertificates, } flattenedServerCertificateConfiguration, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) @@ -891,7 +930,7 @@ func flattenServerCertificateConfigurations(ctx context.Context, serverCertifica return listVal, diags } -func flattenCheckCertificateRevocationStatus(ctx context.Context, checkCertificateRevocationStatus *networkfirewall.CheckCertificateRevocationStatusActions)(types.List, diag.Diagnostics){ +func flattenCheckCertificateRevocationStatus(ctx context.Context, checkCertificateRevocationStatus *networkfirewall.CheckCertificateRevocationStatusActions) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes} @@ -930,8 +969,8 @@ func flattenServerCertificates(ctx context.Context, serverCertificateList []*net "resource_arn": flex.StringToFramework(ctx, serverCertificate.ResourceArn), } - flattenedServerCertificate, d:= types.ObjectValue(serverCertificatesAttrTypes, obj) - + flattenedServerCertificate, d := types.ObjectValue(serverCertificatesAttrTypes, obj) + diags.Append(d...) elems = append(elems, flattenedServerCertificate) } @@ -942,7 +981,7 @@ func flattenServerCertificates(ctx context.Context, serverCertificateList []*net return listVal, diags } -func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ +func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} @@ -966,7 +1005,7 @@ func flattenCertificates(ctx context.Context, certificateList []*networkfirewall return listVal, diags } -func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.TlsCertificateData)(types.List, diag.Diagnostics){ +func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} @@ -975,10 +1014,10 @@ func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.Tls } obj := map[string]attr.Value{ - "certificate_arn": flex.StringToFramework(ctx, certificate.CertificateArn), + "certificate_arn": flex.StringToFramework(ctx, certificate.CertificateArn), "certificate_serial": flex.StringToFramework(ctx, certificate.CertificateSerial), - "status": flex.StringToFramework(ctx, certificate.Status), - "status_message": flex.StringToFramework(ctx, certificate.StatusMessage), + "status": flex.StringToFramework(ctx, certificate.Status), + "status_message": flex.StringToFramework(ctx, certificate.StatusMessage), } objVal, d := types.ObjectValue(certificatesAttrTypes, obj) diags.Append(d...) @@ -990,8 +1029,7 @@ func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.Tls } - -func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertificateScope)(types.List, diag.Diagnostics){ +func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertificateScope) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: scopeAttrTypes} @@ -1016,13 +1054,12 @@ func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertific sources, d := flattenSourceDestinations(ctx, scope.Sources) diags.Append(d...) - obj := map[string]attr.Value{ "destination_ports": destinationPorts, - "destinations": destinations, - "protocols": protocols, - "source_ports": sourcePorts, - "sources": sources, + "destinations": destinations, + "protocols": protocols, + "source_ports": sourcePorts, + "sources": sources, } objVal, d := types.ObjectValue(scopeAttrTypes, obj) diags.Append(d...) @@ -1037,7 +1074,7 @@ func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertific } -func flattenProtocols(ctx context.Context, list []*int64)(types.List, diag.Diagnostics){ +func flattenProtocols(ctx context.Context, list []*int64) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.Int64Type @@ -1107,7 +1144,7 @@ func flattenPortRange(ctx context.Context, ranges []*networkfirewall.PortRange) obj := map[string]attr.Value{ "from_port": flex.Int64ToFramework(ctx, portRange.FromPort), - "to_port": flex.Int64ToFramework(ctx, portRange.ToPort), + "to_port": flex.Int64ToFramework(ctx, portRange.ToPort), } objVal, d := types.ObjectValue(portRangeAttrTypes, obj) diags.Append(d...) @@ -1131,7 +1168,7 @@ func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfigurat obj := map[string]attr.Value{ "key_id": flex.StringToFramework(ctx, encryptionConfiguration.KeyId), - "type": flex.StringToFramework(ctx, encryptionConfiguration.Type), + "type": flex.StringToFramework(ctx, encryptionConfiguration.Type), } objVal, d := types.ObjectValue(encryptionConfigurationAttrTypes, obj) diags.Append(d...) @@ -1208,59 +1245,71 @@ func expandTLSEncryptionConfiguration(tfList []encryptionConfigurationData) *net tfObj := tfList[0] apiObject := &networkfirewall.EncryptionConfiguration{ KeyId: aws.String(tfObj.KeyId.ValueString()), - Type: aws.String(tfObj.Type.ValueString()), + Type: aws.String(tfObj.Type.ValueString()), } return apiObject } -func expandTLSInspectionConfiguration(tfList []tlsInspectionConfigurationData) *networkfirewall.TLSInspectionConfiguration { +func expandTLSInspectionConfiguration(ctx context.Context, tfList []tlsInspectionConfigurationData) *networkfirewall.TLSInspectionConfiguration { + var diags diag.Diagnostics + if len(tfList) == 0 { return nil } - - // var apiObject []networkfirewall.TLSInspectionConfiguration tfObj := tfList[0] - // for _, item := range tfList { - apiObject := &networkfirewall.TLSInspectionConfiguration{} - if !tfObj.ServerCertificateConfiguration.IsNull() { - var serverConfig []serverCertificateConfigurationsData - apiObject.ServerCertificateConfigurations = expandServerCertificateConfigurations(serverConfig) + var serverCertConfig []serverCertificateConfigurationsData + diags.Append(tfObj.ServerCertificateConfiguration.ElementsAs(ctx, &serverCertConfig, false)...) + + fmt.Printf("diags: %v\n", diags) + + apiObject := &networkfirewall.TLSInspectionConfiguration{ + ServerCertificateConfigurations: expandServerCertificateConfigurations(ctx, serverCertConfig), } - - // apiObject = append(apiObject, conf) - + return apiObject } -func expandServerCertificateConfigurations(tfList []serverCertificateConfigurationsData) []*networkfirewall.ServerCertificateConfiguration { +func expandServerCertificateConfigurations(ctx context.Context, tfList []serverCertificateConfigurationsData) []*networkfirewall.ServerCertificateConfiguration { + var diags diag.Diagnostics + var apiObject []*networkfirewall.ServerCertificateConfiguration for _, item := range tfList { - conf := &networkfirewall.ServerCertificateConfiguration{ - CertificateAuthorityArn: aws.String(item.CertificateAuthorityArn.ValueString()), + conf := &networkfirewall.ServerCertificateConfiguration{} + + // Configure CertificateAuthorityArn for outbound SSL/TLS inspection + if !item.CertificateAuthorityArn.IsNull() { + conf.CertificateAuthorityArn = aws.String(item.CertificateAuthorityArn.ValueString()) } if !item.CheckCertificateRevocationsStatus.IsNull() { var certificateRevocationStatus []checkCertificateRevocationStatusData - conf.CheckCertificateRevocationStatus = expandCheckCertificateRevocationStatus(certificateRevocationStatus) + diags.Append(item.CheckCertificateRevocationsStatus.ElementsAs(ctx, &certificateRevocationStatus, false)...) + conf.CheckCertificateRevocationStatus = expandCheckCertificateRevocationStatus(ctx, certificateRevocationStatus) } if !item.Scope.IsNull() { var scopesList []scopeData - conf.Scopes = expandScopes(scopesList) + diags.Append(item.Scope.ElementsAs(ctx, &scopesList, false)...) + conf.Scopes = expandScopes(ctx, scopesList) } + // Configure ServerCertificates for inbound SSL/TLS inspection if !item.ServerCertificates.IsNull() { var serverCertificates []serverCertificatesData + diags.Append(item.ServerCertificates.ElementsAs(ctx, &serverCertificates, false)...) conf.ServerCertificates = expandServerCertificates(serverCertificates) } apiObject = append(apiObject, conf) } + + fmt.Printf("diags: %v\n", diags) + return apiObject } -func expandCheckCertificateRevocationStatus(tfList []checkCertificateRevocationStatusData) *networkfirewall.CheckCertificateRevocationStatusActions{ +func expandCheckCertificateRevocationStatus(ctx context.Context, tfList []checkCertificateRevocationStatusData) *networkfirewall.CheckCertificateRevocationStatusActions { if len(tfList) == 0 { return nil } @@ -1286,7 +1335,8 @@ func expandServerCertificates(tfList []serverCertificatesData) []*networkfirewal return apiObject } -func expandScopes(tfList []scopeData) []*networkfirewall.ServerCertificateScope { +func expandScopes(ctx context.Context, tfList []scopeData) []*networkfirewall.ServerCertificateScope { + var diags diag.Diagnostics var apiObject []*networkfirewall.ServerCertificateScope for _, tfObj := range tfList { @@ -1295,33 +1345,39 @@ func expandScopes(tfList []scopeData) []*networkfirewall.ServerCertificateScope } if !tfObj.DestinationPorts.IsNull() { var destinationPorts []portRangeData - item.DestinationPorts = expandPortRange(destinationPorts) + diags.Append(tfObj.DestinationPorts.ElementsAs(ctx, &destinationPorts, false)...) + item.DestinationPorts = expandPortRange(ctx, destinationPorts) } if !tfObj.Destinations.IsNull() { var destinations []sourceDestinationData - item.Destinations = expandSourceDestinations(destinations) + diags.Append(tfObj.Destinations.ElementsAs(ctx, &destinations, false)...) + item.Destinations = expandSourceDestinations(ctx, destinations) } if !tfObj.SourcePorts.IsNull() { var sourcePorts []portRangeData - item.SourcePorts = expandPortRange(sourcePorts) + diags.Append(tfObj.SourcePorts.ElementsAs(ctx, &sourcePorts, false)...) + item.SourcePorts = expandPortRange(ctx, sourcePorts) } if !tfObj.Sources.IsNull() { var sources []sourceDestinationData - item.Sources = expandSourceDestinations(sources) + diags.Append(tfObj.Sources.ElementsAs(ctx, &sources, false)...) + item.Sources = expandSourceDestinations(ctx, sources) } apiObject = append(apiObject, item) } + fmt.Printf("diags: %v\n", diags) + return apiObject } -func expandPortRange(tfList []portRangeData) []*networkfirewall.PortRange { +func expandPortRange(ctx context.Context, tfList []portRangeData) []*networkfirewall.PortRange { var apiObject []*networkfirewall.PortRange for _, tfObj := range tfList { item := &networkfirewall.PortRange{ FromPort: aws.Int64(tfObj.FromPort.ValueInt64()), - ToPort: aws.Int64(tfObj.ToPort.ValueInt64()), + ToPort: aws.Int64(tfObj.ToPort.ValueInt64()), } apiObject = append(apiObject, item) } @@ -1329,7 +1385,7 @@ func expandPortRange(tfList []portRangeData) []*networkfirewall.PortRange { return apiObject } -func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall.Address { +func expandSourceDestinations(ctx context.Context, tfList []sourceDestinationData) []*networkfirewall.Address { var apiObject []*networkfirewall.Address for _, tfObj := range tfList { @@ -1352,7 +1408,6 @@ func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall // return item // } - // TIP: Even when you have a list with max length of 1, this plural function // works brilliantly. However, if the AWS API takes a structure rather than a // slice of structures, you will not need it. @@ -1395,19 +1450,19 @@ func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall // With Terraform Plugin-Framework configurations are deserialized into // Go types, providing type safety without the need for type assertions. // These structs should match the schema definition exactly, and the `tfsdk` -// tag value should match the attribute name. +// tag value should match the attribute name. // -// Nested objects are represented in their own data struct. These will +// Nested objects are represented in their own data struct. These will // also have a corresponding attribute type mapping for use inside flex // functions. // // See more: // https://developer.hashicorp.com/terraform/plugin/framework/handling-data/accessing-values type resourceTLSInspectionConfigurationData struct { - ARN types.String `tfsdk:"arn"` - EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` - Certificates types.List `tfsdk:"certificates"` - CertificateAuthority types.List `tfsdk:"certificate_authority"` + ARN types.String `tfsdk:"arn"` + EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` + Certificates types.List `tfsdk:"certificates"` + CertificateAuthority types.List `tfsdk:"certificate_authority"` // ComplexArgument types.List `tfsdk:"complex_argument"` Description types.String `tfsdk:"description"` ID types.String `tfsdk:"id"` @@ -1417,8 +1472,8 @@ type resourceTLSInspectionConfigurationData struct { Status types.String `tfsdk:"status"` TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` Timeouts timeouts.Value `tfsdk:"timeouts"` - Type types.String `tfsdk:"type"` - UpdateToken types.String `tfsdk:"update_token"` + // Type types.String `tfsdk:"type"` + UpdateToken types.String `tfsdk:"update_token"` } type encryptionConfigurationData struct { @@ -1434,14 +1489,14 @@ type encryptionConfigurationData struct { // } type tlsInspectionConfigurationData struct { - ServerCertificateConfiguration types.List `tfsdk:"server_certificate_configuration"` + ServerCertificateConfiguration types.List `tfsdk:"server_certificate_configurations"` } type serverCertificateConfigurationsData struct { - CertificateAuthorityArn types.String `tfsdk:"certificate_authority_arn"` - CheckCertificateRevocationsStatus types.List `tfsdk:"check_certificate_revocations_status"` - Scope types.List `tfsdk:"scope"` - ServerCertificates types.List `tfsdk:"server_certificates"` + CertificateAuthorityArn types.String `tfsdk:"certificate_authority_arn"` + CheckCertificateRevocationsStatus types.List `tfsdk:"check_certificate_revocation_status"` + Scope types.List `tfsdk:"scope"` + ServerCertificates types.List `tfsdk:"server_certificates"` } // type complexArgumentData struct { @@ -1451,10 +1506,10 @@ type serverCertificateConfigurationsData struct { type scopeData struct { DestinationPorts types.List `tfsdk:"destination_ports"` - Destinations types.List `tfsdk:"destinations"` - Protocols types.List `tfsdk:"protocols"` - SourcePorts types.List `tfsdk:"source_ports"` - Sources types.List `tfsdk:"sources"` + Destinations types.List `tfsdk:"destinations"` + Protocols types.List `tfsdk:"protocols"` + SourcePorts types.List `tfsdk:"source_ports"` + Sources types.List `tfsdk:"sources"` } type sourceDestinationData struct { @@ -1463,7 +1518,7 @@ type sourceDestinationData struct { type portRangeData struct { FromPort types.Int64 `tfsdk:"from_port"` - ToPort types.Int64 `tfsdk:"to_port"` + ToPort types.Int64 `tfsdk:"to_port"` } type checkCertificateRevocationStatusData struct { @@ -1478,10 +1533,10 @@ type serverCertificatesData struct { ////////////// var certificatesAttrTypes = map[string]attr.Type{ - "certificate_arn": types.StringType, + "certificate_arn": types.StringType, "certificate_serial": types.StringType, - "status": types.StringType, - "status_message": types.StringType, + "status": types.StringType, + "status_message": types.StringType, } // var complexArgumentAttrTypes = map[string]attr.Type{ @@ -1490,19 +1545,19 @@ var certificatesAttrTypes = map[string]attr.Type{ // } var encryptionConfigurationAttrTypes = map[string]attr.Type{ - "type": types.StringType, + "type": types.StringType, "key_id": types.StringType, } var tlsInspectionConfigurationAttrTypes = map[string]attr.Type{ - "server_certificate_configuration": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes}}, + "server_certificate_configurations": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes}}, } -var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ - "certificate_authority_arn": types.StringType, - "check_certificate_revocations_status": types.ListType{ElemType: types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes}}, - "scope": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, - "server_certificates": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificatesAttrTypes}}, +var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ + "certificate_authority_arn": types.StringType, + "check_certificate_revocation_status": types.ListType{ElemType: types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes}}, + "scope": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, + "server_certificates": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificatesAttrTypes}}, } var checkCertificateRevocationStatusAttrTypes = map[string]attr.Type{ @@ -1513,10 +1568,10 @@ var checkCertificateRevocationStatusAttrTypes = map[string]attr.Type{ var ( scopeAttrTypes = map[string]attr.Type{ "destination_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, - "destinations": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, - "protocols": types.ListType{ElemType: types.Int64Type}, - "source_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, - "sources": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, + "destinations": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, + "protocols": types.ListType{ElemType: types.Int64Type}, + "source_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, + "sources": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, } sourceDestinationAttrTypes = map[string]attr.Type{ @@ -1525,10 +1580,10 @@ var ( portRangeAttrTypes = map[string]attr.Type{ "from_port": types.Int64Type, - "to_port": types.Int64Type, + "to_port": types.Int64Type, } ) var serverCertificatesAttrTypes = map[string]attr.Type{ "resource_arn": types.StringType, -} \ No newline at end of file +} diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index cbf28a4cf23..c93a27c3c24 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -19,6 +19,7 @@ import ( "context" "errors" "fmt" + "os" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -66,55 +67,55 @@ import ( // Cut and dry functions using well-used patterns, like typical flatteners and // expanders, don't need unit testing. However, if they are complex or // intricate, they should be unit tested. -func TestTLSInspectionConfigurationExampleUnitTest(t *testing.T) { - t.Parallel() - - testCases := []struct { - TestName string - Input string - Expected string - Error bool - }{ - { - TestName: "empty", - Input: "", - Expected: "", - Error: true, - }, - { - TestName: "descriptive name", - Input: "some input", - Expected: "some output", - Error: false, - }, - { - TestName: "another descriptive name", - Input: "more input", - Expected: "more output", - Error: false, - }, - } +// func TestTLSInspectionConfigurationExampleUnitTest(t *testing.T) { +// t.Parallel() + +// testCases := []struct { +// TestName string +// Input string +// Expected string +// Error bool +// }{ +// { +// TestName: "empty", +// Input: "", +// Expected: "", +// Error: true, +// }, +// { +// TestName: "descriptive name", +// Input: "some input", +// Expected: "some output", +// Error: false, +// }, +// { +// TestName: "another descriptive name", +// Input: "more input", +// Expected: "more output", +// Error: false, +// }, +// } - for _, testCase := range testCases { - testCase := testCase - t.Run(testCase.TestName, func(t *testing.T) { - t.Parallel() - got, err := tfnetworkfirewall.FunctionFromResource(testCase.Input) +// for _, testCase := range testCases { +// testCase := testCase +// t.Run(testCase.TestName, func(t *testing.T) { +// t.Parallel() +// got, err := tfnetworkfirewall.FunctionFromResource(testCase.Input) - if err != nil && !testCase.Error { - t.Errorf("got error (%s), expected no error", err) - } +// if err != nil && !testCase.Error { +// t.Errorf("got error (%s), expected no error", err) +// } - if err == nil && testCase.Error { - t.Errorf("got (%s) and no error, expected error", got) - } +// if err == nil && testCase.Error { +// t.Errorf("got (%s) and no error, expected error", got) +// } - if got != testCase.Expected { - t.Errorf("got %s, expected %s", got, testCase.Expected) - } - }) - } -} +// if got != testCase.Expected { +// t.Errorf("got %s, expected %s", got, testCase.Expected) +// } +// }) +// } +// } // TIP: ==== ACCEPTANCE TESTS ==== // This is an example of a basic acceptance test. This should test as much of @@ -123,6 +124,10 @@ func TestTLSInspectionConfigurationExampleUnitTest(t *testing.T) { // resource name. // // Acceptance test access AWS and cost money to run. + +// NOTE: acceptance tests require environment variable ACM_CERTIFICATE_ARN +// to be set and the ACM certificate to be validated during testing. + func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { ctx := acctest.Context(t) // TIP: This is a long-running test guard for tests that run longer than @@ -132,13 +137,15 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { } var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput + // domainName := acctest.ACMCertificateDomainFromEnv(t) + certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_tls_inspection_configuration.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) + // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), @@ -146,7 +153,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_basic(rName), + Config: testAccTLSInspectionConfigurationConfig_basic(rName, certificateArn), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), // resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), @@ -161,10 +168,10 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, }, }, }) @@ -176,22 +183,23 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_disappears(t *testing.T) { t.Skip("skipping long-running test in short mode") } - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationResponse + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput + domainName := acctest.ACMCertificateDomainFromEnv(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_tls_inspection_configuration.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, names.NetworkFirewallEndpointID) - testAccPreCheck(t) + acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) + testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewallEndpointID), + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_basic(rName, testAccTLSInspectionConfigurationVersionNewer), + Config: testAccTLSInspectionConfigurationConfig_basic(rName, domainName), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), // TIP: The Plugin-Framework disappears helper is similar to the Plugin-SDK version, @@ -210,7 +218,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_disappears(t *testing.T) { func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_networkfirewall_tls_inspection_configuration" { @@ -218,11 +226,9 @@ func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource } input := &networkfirewall.DescribeTLSInspectionConfigurationInput{ - TLSInspectionConfigurationId: aws.String(rs.Primary.ID), + TLSInspectionConfigurationArn: aws.String(rs.Primary.Attributes["arn"]), } - _, err := conn.DescribeTLSInspectionConfiguration(ctx, &networkfirewall.DescribeTLSInspectionConfigurationInput{ - TLSInspectionConfigurationId: aws.String(rs.Primary.ID), - }) + _, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, input) if errs.IsA[*types.ResourceNotFoundException](err) { return nil } @@ -277,94 +283,102 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name stri // } // } -func testAccCheckTLSInspectionConfigurationNotRecreated(before, after *networkfirewall.DescribeTLSInspectionConfigurationResponse) resource.TestCheckFunc { - return func(s *terraform.State) error { - if before, after := aws.ToString(before.TLSInspectionConfigurationId), aws.ToString(after.TLSInspectionConfigurationId); before != after { - return create.Error(names.NetworkFirewall, create.ErrActionCheckingNotRecreated, tfnetworkfirewall.ResNameTLSInspectionConfiguration, aws.ToString(before.TLSInspectionConfigurationId), errors.New("recreated")) - } +// func testAccCheckTLSInspectionConfigurationNotRecreated(before, after *networkfirewall.DescribeTLSInspectionConfigurationOutput) resource.TestCheckFunc { +// return func(s *terraform.State) error { +// if before, after := aws.ToString(before.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId), aws.ToString(after.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId); before != after { +// return create.Error(names.NetworkFirewall, create.ErrActionCheckingNotRecreated, tfnetworkfirewall.ResNameTLSInspectionConfiguration, aws.ToString(before.TLSInspectionConfigurationId), errors.New("recreated")) +// } - return nil - } +// return nil +// } +// } + +func testAccTLSInspectionConfigurationConfig_base(domainName string) string { + return fmt.Sprintf(` +resource "aws_acm_certificate" "cert" { + domain_name = %[1]q + validation_method = "DNS" +} +`, domainName) } -func testAccTLSInspectionConfigurationConfig_basic(rName string) string { +func testAccTLSInspectionConfigurationConfig_basic(rName, certificateARN string) string { + // return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_base(domainName), fmt.Sprintf(` return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q + description = "test" tls_inspection_configuration { server_certificate_configurations { - certificate_authority_arn = - check_certificate_revocation_status { - revoked_status_action = "PASS" - unknown_status_action = "PASS" - } - server_certificates { - resource_arn = - } - scopes { - protocols = [ 6 ] - destination_ports { - from_port = 443 - to_port = 443 - } - destinations { - address_definition = "0.0.0.0/0" - } - source_ports { - from_port = 0 - to_port = 65535 - } - sources { - address_definition = "0.0.0.0/0" - } - } - } - } + server_certificates { + resource_arn = %[2]q + } + scope { + protocols = [ 6 ] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } } -`, rName) +`, rName, certificateARN) } func testAccTLSInspectionConfigurationConfig_withEncryptionConfiguration(rName string) string { return fmt.Sprintf(` resource "aws_kms_key" "test" { - description = "test" - deletion_window_in_days = 10 - } + description = "test" + deletion_window_in_days = 10 +} resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q - description = "test" - encryption_configuration { - key_id = aws_kms_key.test.key_id - type = "CUSTOMER_KMS" - } - tls_inspection_configuration { - server_certificate_configurations { - certificate_authority_arn = - check_certificate_revocation_status { - revoked_status_action = "PASS" - unknown_status_action = "PASS" - } - server_certificates { - resource_arn = - } - scopes { - protocols = [ 6 ] - destination_ports { - from_port = 443 - to_port = 443 - } - destinations { - address_definition = "0.0.0.0/0" - } - source_ports { - from_port = 0 - to_port = 65535 - } - sources { - address_definition = "0.0.0.0/0" - } - + name = %[1]q + description = "test" + encryption_configuration { + key_id = aws_kms_key.test.key_id + type = "CUSTOMER_KMS" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = + check_certificate_revocation_status { + revoked_status_action = "PASS" + unknown_status_action = "PASS" + } + server_certificates { + resource_arn = + } + scope { + protocols = [ 6 ] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } } `, rName) } From 579c5c4031b517b17a13a438cdf6dc367682e949 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:00:30 -0500 Subject: [PATCH 09/68] [WIP] Additional flex fixes, TODO: fix imports, ID --- .../tls_inspection_configuration.go | 136 ++++++++++++------ .../tls_inspection_configuration_test.go | 20 ++- 2 files changed, 105 insertions(+), 51 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 9356d369baf..a3d72a35140 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -29,13 +29,16 @@ import ( "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" - // "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/framework" "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" @@ -153,15 +156,27 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, "last_modified_time": schema.StringAttribute{ Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, }, "number_of_associations": schema.Int64Attribute{ Computed: true, + PlanModifiers: []planmodifier.Int64{ + int64planmodifier.UseStateForUnknown(), + }, }, "status": schema.StringAttribute{ Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, }, "update_token": schema.StringAttribute{ Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, }, }, Blocks: map[string]schema.Block{ @@ -206,9 +221,16 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res Attributes: map[string]schema.Attribute{ "key_id": schema.StringAttribute{ Optional: true, + Computed: true, + Default: stringdefault.StaticString("AWS_OWNED_KMS_KEY"), }, "type": schema.StringAttribute{ - Required: true, + Optional: true, + Computed: true, + Default: stringdefault.StaticString("AWS_OWNED_KMS_KEY"), + Validators: []validator.String{ + enum.FrameworkValidate[awstypes.EncryptionType](), + }, }, }, }, @@ -427,10 +449,19 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res // Output consists only of TLSInspectionConfigurationResponse plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) + plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) + + // Read to get computed attributes not returned from create + readComputed, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, plan.ARN.ValueString()) + + // Set computed attributes + plan.LastModifiedTime = flex.StringValueToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) + plan.NumberOfAssociations = flex.Int64ToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.NumberOfAssociations) + plan.Status = flex.StringToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) // TIP: -- 6. Use a waiter to wait for create to complete createTimeout := r.CreateTimeout(ctx, plan.Timeouts) - _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ID.ValueString(), createTimeout) + _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ARN.ValueString(), createTimeout) if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForCreation, ResNameTLSInspectionConfiguration, plan.Name.String(), err), @@ -507,18 +538,24 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou encryptionConfiguration, d := flattenTLSEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) resp.Diagnostics.Append(d...) state.EncryptionConfiguration = encryptionConfiguration + fmt.Printf("diags for encryption config: %v\n", resp.Diagnostics) certificateAuthority, d := flattenTLSCertificate(ctx, out.TLSInspectionConfigurationResponse.CertificateAuthority) resp.Diagnostics.Append(d...) state.CertificateAuthority = certificateAuthority + fmt.Printf("diags for certificate authority: %v\n", resp.Diagnostics) certificates, d := flattenCertificates(ctx, out.TLSInspectionConfigurationResponse.Certificates) resp.Diagnostics.Append(d...) state.Certificates = certificates + fmt.Printf("diags for certificates: %v\n", resp.Diagnostics) - tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) - resp.Diagnostics.Append(d...) - state.TLSInspectionConfiguration = tlsInspectionConfiguration + resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) + + // tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) + // resp.Diagnostics.Append(d...) + // state.TLSInspectionConfiguration = tlsInspectionConfiguration + // fmt.Printf("diags for tls: %v\n", resp.Diagnostics) // TIP: Setting a complex type. // complexArgument, d := flattenComplexArgument(ctx, out.ComplexArgument) @@ -527,6 +564,9 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou // TIP: -- 6. Set the state resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) + + // Print diagnostics + } func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { @@ -639,7 +679,7 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res // TIP: -- 5. Use a waiter to wait for update to complete updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) - _, err := waitTLSInspectionConfigurationUpdated(ctx, conn, plan.ID.ValueString(), updateTimeout) + _, err := waitTLSInspectionConfigurationUpdated(ctx, conn, plan.ARN.ValueString(), updateTimeout) if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForUpdate, ResNameTLSInspectionConfiguration, plan.ID.String(), err), @@ -685,8 +725,11 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res // TIP: -- 5. Use a waiter to wait for delete to complete deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) - _, err = waitTLSInspectionConfigurationDeleted(ctx, conn, state.ID.ValueString(), deleteTimeout) + _, err = waitTLSInspectionConfigurationDeleted(ctx, conn, state.ARN.ValueString(), deleteTimeout) if err != nil { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } resp.Diagnostics.AddError( create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForDeletion, ResNameTLSInspectionConfiguration, state.ID.String(), err), err.Error(), @@ -703,7 +746,8 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res // See more: // https://developer.hashicorp.com/terraform/plugin/framework/resources/import func (r *resourceTLSInspectionConfiguration) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) + fmt.Println("Import ID", path.Root("arn")) + resource.ImportStatePassthroughID(ctx, path.Root("arn"), req, resp) } // TIP: ==== STATUS CONSTANTS ==== @@ -730,11 +774,11 @@ const ( // exported (i.e., capitalized). // // You will need to adjust the parameters and names to fit the service. -func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, id string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { +func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{}, - Target: []string{statusNormal}, - Refresh: statusTLSInspectionConfiguration(ctx, conn, id), + Target: []string{networkfirewall.ResourceStatusActive}, + Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), Timeout: timeout, NotFoundChecks: 20, ContinuousTargetOccurence: 2, @@ -755,7 +799,7 @@ func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfir func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{statusChangePending}, - Target: []string{statusUpdated}, + Target: []string{networkfirewall.ResourceStatusActive}, Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), Timeout: timeout, NotFoundChecks: 20, @@ -772,11 +816,11 @@ func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfir // TIP: A deleted waiter is almost like a backwards created waiter. There may // be additional pending states, however. -func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, id string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { +func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{statusDeleting, statusNormal}, + Pending: []string{networkfirewall.ResourceStatusDeleting, networkfirewall.ResourceStatusActive}, Target: []string{}, - Refresh: statusTLSInspectionConfiguration(ctx, conn, id), + Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), Timeout: timeout, } @@ -871,19 +915,20 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo // return listVal, diags // } -func flattenTLSInspectionConfiguration(ctx context.Context, apiObject *networkfirewall.TLSInspectionConfiguration) (types.List, diag.Diagnostics) { +func flattenTLSInspectionConfiguration(ctx context.Context, tlsInspectionConfiguration *networkfirewall.TLSInspectionConfiguration) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: tlsInspectionConfigurationAttrTypes} - if apiObject == nil { + if tlsInspectionConfiguration == nil { return types.ListNull(elemType), diags } - serverCertConfig, d := flattenServerCertificateConfigurations(ctx, apiObject.ServerCertificateConfigurations) + // + flattenedConfig, d := flattenServerCertificateConfigurations(ctx, tlsInspectionConfiguration.ServerCertificateConfigurations) diags.Append(d...) obj := map[string]attr.Value{ - "server_certificate_configurations": serverCertConfig, + "server_certificate_configurations": flattenedConfig, } objVal, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) diags.Append(d...) @@ -899,24 +944,28 @@ func flattenServerCertificateConfigurations(ctx context.Context, serverCertifica var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes} - if len(serverCertificateConfigurations) == 0 { + if serverCertificateConfigurations == nil { return types.ListNull(elemType), diags } elems := []attr.Value{} for _, serverCertificateConfiguration := range serverCertificateConfigurations { - checkCertRevocationStatus, d := flattenCheckCertificateRevocationStatus(ctx, serverCertificateConfiguration.CheckCertificateRevocationStatus) - diags.Append(d...) - scopes, d := flattenScopes(ctx, serverCertificateConfiguration.Scopes) - diags.Append(d...) - serverCertificates, d := flattenServerCertificates(ctx, serverCertificateConfiguration.ServerCertificates) - diags.Append(d...) + if serverCertificateConfiguration == nil { + continue + } + + // checkCertRevocationStatus, d := flattenCheckCertificateRevocationStatus(ctx, serverCertificateConfiguration.CheckCertificateRevocationStatus) + // diags.Append(d...) + // scopes, d := flattenScopes(ctx, serverCertificateConfiguration.Scopes) + // diags.Append(d...) + // serverCertificates, d := flattenServerCertificates(ctx, serverCertificateConfiguration.ServerCertificates) + // diags.Append(d...) obj := map[string]attr.Value{ - "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), - "check_certificate_revocation_status": checkCertRevocationStatus, - "scopes": scopes, - "server_certificates": serverCertificates, + "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), + // "check_certificate_revocation_status": checkCertRevocationStatus, + // "scopes": scopes, + // "server_certificates": serverCertificates, } flattenedServerCertificateConfiguration, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) @@ -977,6 +1026,7 @@ func flattenServerCertificates(ctx context.Context, serverCertificateList []*net listVal, d := types.ListValue(elemType, elems) diags.Append(d...) + fmt.Printf("diags from flattenServerCertificates: %v\n", diags) return listVal, diags } @@ -1263,8 +1313,6 @@ func expandTLSInspectionConfiguration(ctx context.Context, tfList []tlsInspectio var serverCertConfig []serverCertificateConfigurationsData diags.Append(tfObj.ServerCertificateConfiguration.ElementsAs(ctx, &serverCertConfig, false)...) - fmt.Printf("diags: %v\n", diags) - apiObject := &networkfirewall.TLSInspectionConfiguration{ ServerCertificateConfigurations: expandServerCertificateConfigurations(ctx, serverCertConfig), } @@ -1304,8 +1352,6 @@ func expandServerCertificateConfigurations(ctx context.Context, tfList []serverC apiObject = append(apiObject, conf) } - fmt.Printf("diags: %v\n", diags) - return apiObject } @@ -1340,8 +1386,11 @@ func expandScopes(ctx context.Context, tfList []scopeData) []*networkfirewall.Se var apiObject []*networkfirewall.ServerCertificateScope for _, tfObj := range tfList { - item := &networkfirewall.ServerCertificateScope{ - // Protocols: aws.Int64Slice(), + item := &networkfirewall.ServerCertificateScope{} + if !tfObj.Protocols.IsNull() { + protocols := []*int64{} + diags.Append(tfObj.Protocols.ElementsAs(ctx, &protocols, false)...) + item.Protocols = protocols } if !tfObj.DestinationPorts.IsNull() { var destinationPorts []portRangeData @@ -1459,11 +1508,10 @@ func expandSourceDestinations(ctx context.Context, tfList []sourceDestinationDat // See more: // https://developer.hashicorp.com/terraform/plugin/framework/handling-data/accessing-values type resourceTLSInspectionConfigurationData struct { - ARN types.String `tfsdk:"arn"` - EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` - Certificates types.List `tfsdk:"certificates"` - CertificateAuthority types.List `tfsdk:"certificate_authority"` - // ComplexArgument types.List `tfsdk:"complex_argument"` + ARN types.String `tfsdk:"arn"` + EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` + Certificates types.List `tfsdk:"certificates"` + CertificateAuthority types.List `tfsdk:"certificate_authority"` Description types.String `tfsdk:"description"` ID types.String `tfsdk:"id"` LastModifiedTime types.String `tfsdk:"last_modified_time"` @@ -1472,8 +1520,7 @@ type resourceTLSInspectionConfigurationData struct { Status types.String `tfsdk:"status"` TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` Timeouts timeouts.Value `tfsdk:"timeouts"` - // Type types.String `tfsdk:"type"` - UpdateToken types.String `tfsdk:"update_token"` + UpdateToken types.String `tfsdk:"update_token"` } type encryptionConfigurationData struct { @@ -1551,6 +1598,7 @@ var encryptionConfigurationAttrTypes = map[string]attr.Type{ var tlsInspectionConfigurationAttrTypes = map[string]attr.Type{ "server_certificate_configurations": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes}}, + //"server_certificate_configurations": fwtypes.ListNestedObjectValueOf[serverCertificateConfigurationAttrTypes], } var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index c93a27c3c24..56d3997c22c 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -167,12 +167,12 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { // acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "networkfirewall", regexache.MustCompile(`tlsinspectionconfiguration:+.`)), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, - }, + // { + // ResourceName: resourceName, + // ImportState: true, + // ImportStateVerify: true, + // // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + // }, }, }) } @@ -304,10 +304,14 @@ resource "aws_acm_certificate" "cert" { func testAccTLSInspectionConfigurationConfig_basic(rName, certificateARN string) string { // return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_base(domainName), fmt.Sprintf(` - return fmt.Sprintf(` + foo := fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" + encryption_configuration { + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" + } tls_inspection_configuration { server_certificate_configurations { server_certificates { @@ -334,6 +338,8 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } `, rName, certificateARN) + fmt.Println(foo) + return foo } func testAccTLSInspectionConfigurationConfig_withEncryptionConfiguration(rName string) string { From cfff153eae44de163dba6e2711de7750513a2a73 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:03:10 -0500 Subject: [PATCH 10/68] [WIP] Fix ResourceNotFound on delete --- .../networkfirewall/tls_inspection_configuration.go | 8 +++----- .../networkfirewall/tls_inspection_configuration_test.go | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index a3d72a35140..450e392ad3d 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -693,10 +693,8 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res } func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - // TIP: -- 2. Fetch the state var state resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { @@ -713,7 +711,7 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res // TIP: On rare occassions, the API returns a not found error after deleting a // resource. If that happens, we don't want it to show up as an error. if err != nil { - if errs.IsA[*awstypes.ResourceNotFoundException](err) { + if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { return } resp.Diagnostics.AddError( @@ -727,7 +725,7 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) _, err = waitTLSInspectionConfigurationDeleted(ctx, conn, state.ARN.ValueString(), deleteTimeout) if err != nil { - if errs.IsA[*awstypes.ResourceNotFoundException](err) { + if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { return } resp.Diagnostics.AddError( @@ -866,7 +864,7 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo out, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, in) if err != nil { - if errs.IsA[*awstypes.ResourceNotFoundException](err) { + if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: in, diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 56d3997c22c..5dc95f95420 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -23,7 +23,6 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/aws/aws-sdk-go/service/networkfirewall" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -229,7 +228,7 @@ func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource TLSInspectionConfigurationArn: aws.String(rs.Primary.Attributes["arn"]), } _, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, input) - if errs.IsA[*types.ResourceNotFoundException](err) { + if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { return nil } if err != nil { From 78244ce9a75b2bfece92d552d616d59bd53c02e5 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:36:39 -0500 Subject: [PATCH 11/68] [WIP] Ingress acceptance tests --- .../tls_inspection_configuration_test.go | 179 ++++++++++++++---- 1 file changed, 140 insertions(+), 39 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 5dc95f95420..cfe72db3e80 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -22,6 +22,7 @@ import ( "os" "testing" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go/service/networkfirewall" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" @@ -127,19 +128,82 @@ import ( // NOTE: acceptance tests require environment variable ACM_CERTIFICATE_ARN // to be set and the ACM certificate to be validated during testing. -func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { +func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) { ctx := acctest.Context(t) - // TIP: This is a long-running test guard for tests that run longer than - // 300s (5 min) generally. if testing.Short() { t.Skip("skipping long-running test in short mode") } var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - // domainName := acctest.ACMCertificateDomainFromEnv(t) certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") + if certificateArn == "" { + t.Skipf("Environment variable %s is not set, skipping test", certificateArn) + } + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateArn), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ + "key_id": "AWS_OWNED_KMS_KEY", + "type": "AWS_OWNED_KMS_KEY", + }), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), + resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), + resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + ), + }, + // { + // ResourceName: resourceName, + // ImportState: true, + // ImportStateVerify: true, + // // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + // }, + }, + }) +} + +func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfiguration(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput + certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") + if certificateArn == "" { + t.Skipf("Environment variable %s is not set, skipping test", certificateArn) + } rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + keyName := "aws_kms_key.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { @@ -152,18 +216,29 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_basic(rName, certificateArn), + Config: testAccTLSInspectionConfigurationConfig_ingressWithEncryptionConfiguration(rName, certificateArn), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - // resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), - // resource.TestCheckResourceAttrSet(resourceName, "maintenance_window_start_time.0.day_of_week"), - // resource.TestCheckTypeSetElemNestedAttrs(resourceName, "user.*", map[string]string{ - // "console_access": "false", - // "groups.#": "0", - // "username": "Test", - // "password": "TestTest1234", - // }), - // acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "networkfirewall", regexache.MustCompile(`tlsinspectionconfiguration:+.`)), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, "arn"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), + resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), + // resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, // { @@ -198,7 +273,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_disappears(t *testing.T) { CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_basic(rName, domainName), + Config: testAccTLSInspectionConfigurationConfig_ingressBasic(rName, domainName), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), // TIP: The Plugin-Framework disappears helper is similar to the Plugin-SDK version, @@ -292,18 +367,8 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name stri // } // } -func testAccTLSInspectionConfigurationConfig_base(domainName string) string { +func testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateARN string) string { return fmt.Sprintf(` -resource "aws_acm_certificate" "cert" { - domain_name = %[1]q - validation_method = "DNS" -} -`, domainName) -} - -func testAccTLSInspectionConfigurationConfig_basic(rName, certificateARN string) string { - // return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_base(domainName), fmt.Sprintf(` - foo := fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" @@ -337,33 +402,69 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } `, rName, certificateARN) - fmt.Println(foo) - return foo } -func testAccTLSInspectionConfigurationConfig_withEncryptionConfiguration(rName string) string { +func testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName string) string { return fmt.Sprintf(` resource "aws_kms_key" "test" { - description = "test" - deletion_window_in_days = 10 + description = %[1]q + deletion_window_in_days = 7 +} +`, rName) } +func testAccTLSInspectionConfigurationConfig_ingressWithEncryptionConfiguration(rName, certificateARN string) string { + return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName), fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" encryption_configuration { - key_id = aws_kms_key.test.key_id + key_id = aws_kms_key.test.arn type = "CUSTOMER_KMS" } tls_inspection_configuration { server_certificate_configurations { - certificate_authority_arn = - check_certificate_revocation_status { - revoked_status_action = "PASS" - unknown_status_action = "PASS" - } server_certificates { - resource_arn = + resource_arn = %[2]q + } + scope { + protocols = [ 6 ] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +`, rName, certificateARN)) +} + +func testAccTLSInspectionConfigurationConfig_egressBasic(rName, certificateAuthorityARN string) string { + return fmt.Sprintf(` +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + description = "test" + encryption_configuration { + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = %[2]q + check_certificate_revokation_status { + revoked_status_action = "REJECT" + unknown_status_action = "PASS" } scope { protocols = [ 6 ] @@ -385,5 +486,5 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } } -`, rName) +`, rName, certificateAuthorityARN) } From ab2cfadec0f227fbd2ee4c8ffcc755bb6076150c Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:06:29 -0500 Subject: [PATCH 12/68] [WIP] Add egress inspection acceptance tests --- .../tls_inspection_configuration.go | 72 +++++++++++----- .../tls_inspection_configuration_test.go | 83 +++++++++++++++++-- 2 files changed, 127 insertions(+), 28 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 450e392ad3d..4e8af3ca795 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -42,6 +42,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/framework" "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -199,6 +200,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, "certificates": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[certificatesData](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "certificate_arn": schema.StringAttribute{ @@ -215,6 +217,23 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, + + // NestedObject: schema.NestedBlockObject{ + // Attributes: map[string]schema.Attribute{ + // "certificate_arn": schema.StringAttribute{ + // Computed: true, + // }, + // "certificate_serial": schema.StringAttribute{ + // Computed: true, + // }, + // "status": schema.StringAttribute{ + // Computed: true, + // }, + // "status_message": schema.StringAttribute{ + // Computed: true, + // }, + // }, + // }, }, "encryption_configuration": schema.ListNestedBlock{ NestedObject: schema.NestedBlockObject{ @@ -454,11 +473,15 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res // Read to get computed attributes not returned from create readComputed, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, plan.ARN.ValueString()) + fmt.Println("Output from readComputed: ", readComputed) + // Set computed attributes plan.LastModifiedTime = flex.StringValueToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) plan.NumberOfAssociations = flex.Int64ToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.NumberOfAssociations) plan.Status = flex.StringToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) + resp.Diagnostics.Append(flex.Flatten(ctx, readComputed.TLSInspectionConfigurationResponse.Certificates, &plan.Certificates)...) + // TIP: -- 6. Use a waiter to wait for create to complete createTimeout := r.CreateTimeout(ctx, plan.Timeouts) _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ARN.ValueString(), createTimeout) @@ -545,12 +568,14 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou state.CertificateAuthority = certificateAuthority fmt.Printf("diags for certificate authority: %v\n", resp.Diagnostics) - certificates, d := flattenCertificates(ctx, out.TLSInspectionConfigurationResponse.Certificates) - resp.Diagnostics.Append(d...) - state.Certificates = certificates - fmt.Printf("diags for certificates: %v\n", resp.Diagnostics) + // certificates, d := flattenCertificates(ctx, out.TLSInspectionConfigurationResponse.Certificates) + // resp.Diagnostics.Append(d...) + // state.Certificates = certificates + // fmt.Printf("diags for certificates: %v\n", resp.Diagnostics) resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) + resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfigurationResponse.Certificates, &state.Certificates)...) + fmt.Printf("Attempting to flatten Certificates: %v\n", resp.Diagnostics) // tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) // resp.Diagnostics.Append(d...) @@ -1506,19 +1531,20 @@ func expandSourceDestinations(ctx context.Context, tfList []sourceDestinationDat // See more: // https://developer.hashicorp.com/terraform/plugin/framework/handling-data/accessing-values type resourceTLSInspectionConfigurationData struct { - ARN types.String `tfsdk:"arn"` - EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` - Certificates types.List `tfsdk:"certificates"` - CertificateAuthority types.List `tfsdk:"certificate_authority"` - Description types.String `tfsdk:"description"` - ID types.String `tfsdk:"id"` - LastModifiedTime types.String `tfsdk:"last_modified_time"` - Name types.String `tfsdk:"name"` - NumberOfAssociations types.Int64 `tfsdk:"number_of_associations"` - Status types.String `tfsdk:"status"` - TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` - Timeouts timeouts.Value `tfsdk:"timeouts"` - UpdateToken types.String `tfsdk:"update_token"` + ARN types.String `tfsdk:"arn"` + EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` + // Certificates types.List `tfsdk:"certificates"` + Certificates fwtypes.ListNestedObjectValueOf[certificatesData] `tfsdk:"certificates"` + CertificateAuthority types.List `tfsdk:"certificate_authority"` + Description types.String `tfsdk:"description"` + ID types.String `tfsdk:"id"` + LastModifiedTime types.String `tfsdk:"last_modified_time"` + Name types.String `tfsdk:"name"` + NumberOfAssociations types.Int64 `tfsdk:"number_of_associations"` + Status types.String `tfsdk:"status"` + TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + UpdateToken types.String `tfsdk:"update_token"` } type encryptionConfigurationData struct { @@ -1526,12 +1552,12 @@ type encryptionConfigurationData struct { KeyId types.String `tfsdk:"key_id"` } -// type certificatesData struct { -// CertificateArn types.String `tfsdk:"certificate_arn"` -// CertificateSerial types.String `tfsdk:"certificate_serial"` -// Status types.String `tfsdk:"status"` -// StatusMessage types.String `tfsdk:"status_message"` -// } +type certificatesData struct { + CertificateArn types.String `tfsdk:"certificate_arn"` + CertificateSerial types.String `tfsdk:"certificate_serial"` + Status types.String `tfsdk:"status"` + StatusMessage types.String `tfsdk:"status_message"` +} type tlsInspectionConfigurationData struct { ServerCertificateConfiguration types.List `tfsdk:"server_certificate_configurations"` diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index cfe72db3e80..1afa521f277 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -128,6 +128,73 @@ import ( // NOTE: acceptance tests require environment variable ACM_CERTIFICATE_ARN // to be set and the ACM certificate to be validated during testing. +func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput + ca := os.Getenv("ACM_CA_CERTIFICATE_ARN") + if ca == "" { + t.Skipf("Environment variable %s is not set, skipping test", ca) + } + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + commonName := "example.com" + caKey := acctest.TLSRSAPrivateKeyPEM(t, 4096) + caCertificate := acctest.TLSRSAX509SelfSignedCACertificatePEM(t, caKey) + key := acctest.TLSRSAPrivateKeyPEM(t, 4096) + certificate := acctest.TLSRSAX509LocallySignedCertificatePEM(t, caKey, caCertificate, key, commonName) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_egressBasic(rName, certificate, key, caCertificate, ca), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ + "key_id": "AWS_OWNED_KMS_KEY", + "type": "AWS_OWNED_KMS_KEY", + }), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", ca), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.to_port", "65535"), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + ), + }, + // { + // ResourceName: resourceName, + // ImportState: true, + // ImportStateVerify: true, + // // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + // }, + }, + }) +} + func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -176,7 +243,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.to_port", "65535"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), - resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), + // resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, @@ -450,8 +517,14 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { `, rName, certificateARN)) } -func testAccTLSInspectionConfigurationConfig_egressBasic(rName, certificateAuthorityARN string) string { +func testAccTLSInspectionConfigurationConfig_egressBasic(rName, certificate, privateKey, chain, ca string) string { return fmt.Sprintf(` +resource "aws_acm_certificate" "test" { + certificate_body = "%[2]s" + private_key = "%[3]s" + certificate_chain = "%[4]s" +} + resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" @@ -461,8 +534,8 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } tls_inspection_configuration { server_certificate_configurations { - certificate_authority_arn = %[2]q - check_certificate_revokation_status { + certificate_authority_arn = %[5]q + check_certificate_revocation_status { revoked_status_action = "REJECT" unknown_status_action = "PASS" } @@ -486,5 +559,5 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } } -`, rName, certificateAuthorityARN) +`, rName, acctest.TLSPEMEscapeNewlines(certificate), acctest.TLSPEMEscapeNewlines(privateKey), acctest.TLSPEMEscapeNewlines(chain), ca) } From 7ebb3fa51b61f437e11d8d1708b96fc5c42a8ae3 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 19 Jan 2024 16:31:45 -0500 Subject: [PATCH 13/68] Additional egress acceptance tests, fix import --- .../tls_inspection_configuration.go | 106 +++++++++++++----- .../tls_inspection_configuration_test.go | 84 +++++++------- 2 files changed, 118 insertions(+), 72 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 4e8af3ca795..619793a4978 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -287,7 +287,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, - "scope": schema.ListNestedBlock{ + "scopes": schema.ListNestedBlock{ NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "protocols": schema.ListAttribute{ @@ -467,7 +467,8 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res // TIP: -- 5. Using the output from the create function, set the minimum attributes // Output consists only of TLSInspectionConfigurationResponse plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) + // Set ID to ARN since ID value is not used for Describe, Update, Delete or List calls + plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) // Read to get computed attributes not returned from create @@ -521,7 +522,7 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou // TIP: -- 3. Get the resource from AWS using an API Get, List, or Describe- // type function, or, better yet, using a finder. - out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, state.ARN.ValueString()) + out, err := findTLSInspectionConfigurationByID(ctx, conn, state.ID.ValueString()) // TIP: -- 4. Remove resource from state if it is not found if tfresource.NotFound(err) { resp.State.RemoveResource(ctx) @@ -549,7 +550,9 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou // should be appended to resp.Diagnostics. state.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) state.Description = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.Description) - state.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) + + // Set ID to ARN since ID value is not used for Describe, Update, Delete or List calls + state.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) state.Name = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationName) state.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) @@ -577,10 +580,13 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfigurationResponse.Certificates, &state.Certificates)...) fmt.Printf("Attempting to flatten Certificates: %v\n", resp.Diagnostics) - // tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) - // resp.Diagnostics.Append(d...) - // state.TLSInspectionConfiguration = tlsInspectionConfiguration - // fmt.Printf("diags for tls: %v\n", resp.Diagnostics) + resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfiguration, &state.TLSInspectionConfiguration)...) + fmt.Printf("Attempting to flatten TLSInspectionConfiguration: %v\n", resp.Diagnostics) + + tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) + resp.Diagnostics.Append(d...) + state.TLSInspectionConfiguration = tlsInspectionConfiguration + fmt.Printf("diags for tls: %v\n", resp.Diagnostics) // TIP: Setting a complex type. // complexArgument, d := flattenComplexArgument(ctx, out.ComplexArgument) @@ -769,8 +775,7 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res // See more: // https://developer.hashicorp.com/terraform/plugin/framework/resources/import func (r *resourceTLSInspectionConfiguration) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - fmt.Println("Import ID", path.Root("arn")) - resource.ImportStatePassthroughID(ctx, path.Root("arn"), req, resp) + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } // TIP: ==== STATUS CONSTANTS ==== @@ -906,6 +911,30 @@ func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *netwo return out, nil } +func findTLSInspectionConfigurationByID(ctx context.Context, conn *networkfirewall.NetworkFirewall, id string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { + in := &networkfirewall.DescribeTLSInspectionConfigurationInput{ + TLSInspectionConfigurationArn: aws.String(id), + } + + out, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, in) + if err != nil { + if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + return nil, err + } + + if out == nil || out.TLSInspectionConfigurationResponse == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out, nil +} + // TIP: ==== FLEX ==== // Flatteners and expanders ("flex" functions) help handle complex data // types. Flatteners take an API data type and return the equivalent Plugin-Framework @@ -946,14 +975,13 @@ func flattenTLSInspectionConfiguration(ctx context.Context, tlsInspectionConfigu return types.ListNull(elemType), diags } - // flattenedConfig, d := flattenServerCertificateConfigurations(ctx, tlsInspectionConfiguration.ServerCertificateConfigurations) diags.Append(d...) obj := map[string]attr.Value{ "server_certificate_configurations": flattenedConfig, } - objVal, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) + objVal, d := types.ObjectValue(tlsInspectionConfigurationAttrTypes, obj) diags.Append(d...) listVal, d := types.ListValue(elemType, []attr.Value{objVal}) @@ -963,6 +991,28 @@ func flattenTLSInspectionConfiguration(ctx context.Context, tlsInspectionConfigu } +// func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfiguration *networkfirewall.EncryptionConfiguration) (types.List, diag.Diagnostics) { +// var diags diag.Diagnostics +// elemType := types.ObjectType{AttrTypes: encryptionConfigurationAttrTypes} + +// if encryptionConfiguration == nil { +// return types.ListNull(elemType), diags +// } + +// obj := map[string]attr.Value{ +// "key_id": flex.StringToFramework(ctx, encryptionConfiguration.KeyId), +// "type": flex.StringToFramework(ctx, encryptionConfiguration.Type), +// } +// objVal, d := types.ObjectValue(encryptionConfigurationAttrTypes, obj) +// diags.Append(d...) + +// listVal, d := types.ListValue(elemType, []attr.Value{objVal}) +// diags.Append(d...) + +// return listVal, diags + +// } + func flattenServerCertificateConfigurations(ctx context.Context, serverCertificateConfigurations []*networkfirewall.ServerCertificateConfiguration) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes} @@ -973,27 +1023,23 @@ func flattenServerCertificateConfigurations(ctx context.Context, serverCertifica elems := []attr.Value{} for _, serverCertificateConfiguration := range serverCertificateConfigurations { - if serverCertificateConfiguration == nil { - continue - } - - // checkCertRevocationStatus, d := flattenCheckCertificateRevocationStatus(ctx, serverCertificateConfiguration.CheckCertificateRevocationStatus) - // diags.Append(d...) - // scopes, d := flattenScopes(ctx, serverCertificateConfiguration.Scopes) - // diags.Append(d...) - // serverCertificates, d := flattenServerCertificates(ctx, serverCertificateConfiguration.ServerCertificates) - // diags.Append(d...) + checkCertRevocationStatus, d := flattenCheckCertificateRevocationStatus(ctx, serverCertificateConfiguration.CheckCertificateRevocationStatus) + diags.Append(d...) + scopes, d := flattenScopes(ctx, serverCertificateConfiguration.Scopes) + diags.Append(d...) + serverCertificates, d := flattenServerCertificates(ctx, serverCertificateConfiguration.ServerCertificates) + diags.Append(d...) obj := map[string]attr.Value{ - "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), - // "check_certificate_revocation_status": checkCertRevocationStatus, - // "scopes": scopes, - // "server_certificates": serverCertificates, + "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), + "check_certificate_revocation_status": checkCertRevocationStatus, + "scopes": scopes, + "server_certificates": serverCertificates, } - flattenedServerCertificateConfiguration, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) + objVal, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) diags.Append(d...) - elems = append(elems, flattenedServerCertificateConfiguration) + elems = append(elems, objVal) } listVal, d := types.ListValue(elemType, elems) @@ -1566,7 +1612,7 @@ type tlsInspectionConfigurationData struct { type serverCertificateConfigurationsData struct { CertificateAuthorityArn types.String `tfsdk:"certificate_authority_arn"` CheckCertificateRevocationsStatus types.List `tfsdk:"check_certificate_revocation_status"` - Scope types.List `tfsdk:"scope"` + Scope types.List `tfsdk:"scopes"` ServerCertificates types.List `tfsdk:"server_certificates"` } @@ -1628,7 +1674,7 @@ var tlsInspectionConfigurationAttrTypes = map[string]attr.Type{ var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ "certificate_authority_arn": types.StringType, "check_certificate_revocation_status": types.ListType{ElemType: types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes}}, - "scope": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, + "scopes": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, "server_certificates": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificatesAttrTypes}}, } diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 1afa521f277..cc7a7ed7dc2 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -175,22 +175,22 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, - // { - // ResourceName: resourceName, - // ImportState: true, - // ImportStateVerify: true, - // // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, - // }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, }, }) } @@ -234,25 +234,25 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) "type": "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), // resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, - // { - // ResourceName: resourceName, - // ImportState: true, - // ImportStateVerify: true, - // // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, - // }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, }, }) } @@ -295,25 +295,25 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfi resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, "arn"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), // resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, - // { - // ResourceName: resourceName, - // ImportState: true, - // ImportStateVerify: true, - // // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, - // }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, }, }) } @@ -448,7 +448,7 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { server_certificates { resource_arn = %[2]q } - scope { + scopes { protocols = [ 6 ] destination_ports { from_port = 443 @@ -494,7 +494,7 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { server_certificates { resource_arn = %[2]q } - scope { + scopes { protocols = [ 6 ] destination_ports { from_port = 443 @@ -539,7 +539,7 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { revoked_status_action = "REJECT" unknown_status_action = "PASS" } - scope { + scopes { protocols = [ 6 ] destination_ports { from_port = 443 From ad6a6dc5f573ef123123b0a687459e391b47f6f5 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:16:24 -0500 Subject: [PATCH 14/68] Cleanup: skaff comments --- .../tls_inspection_configuration.go | 440 +----------------- 1 file changed, 1 insertion(+), 439 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 619793a4978..232e952b141 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -1,18 +1,6 @@ package networkfirewall import ( - // TIP: ==== IMPORTS ==== - // This is a common set of imports but not customized to your code since - // your code hasn't been written yet. Make sure you, your IDE, or - // goimports -w fixes these imports. - // - // The provider linter wants your imports to be in two groups: first, - // standard library (i.e., "fmt" or "strings"), second, everything else. - // - // Also, AWS Go SDK v2 may handle nested structures differently than v1, - // using the services/networkfirewall/types package. If so, you'll - // need to import types and reference the nested types, e.g., as - // awstypes.. "context" "errors" "fmt" @@ -47,16 +35,6 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -// TIP: ==== FILE STRUCTURE ==== -// All resources should follow this basic outline. Improve this resource's -// maintainability by sticking to it. -// -// 1. Package declaration -// 2. Imports -// 3. Main resource struct with schema method -// 4. Create, read, update, delete methods (in that order) -// 5. Other functions (flatteners, expanders, waiters, finders, etc.) - // Function annotations are used for resource registration to the Provider. DO NOT EDIT. // @FrameworkResource(name="TLS Inspection Configuration") func newResourceTLSInspectionConfiguration(_ context.Context) (resource.ResourceWithConfigure, error) { @@ -87,50 +65,6 @@ func (r *resourceTLSInspectionConfiguration) Metadata(_ context.Context, req res resp.TypeName = "aws_networkfirewall_tls_inspection_configuration" } -// TIP: ==== SCHEMA ==== -// In the schema, add each of the attributes in snake case (e.g., -// delete_automated_backups). -// -// Formatting rules: -// * Alphabetize attributes to make them easier to find. -// * Do not add a blank line between attributes. -// -// Attribute basics: -// - If a user can provide a value ("configure a value") for an -// attribute (e.g., instances = 5), we call the attribute an -// "argument." -// - You change the way users interact with attributes using: -// - Required -// - Optional -// - Computed -// - There are only four valid combinations: -// -// 1. Required only - the user must provide a value -// Required: true, -// -// 2. Optional only - the user can configure or omit a value; do not -// use Default or DefaultFunc -// -// Optional: true, -// -// 3. Computed only - the provider can provide a value but the user -// cannot, i.e., read-only -// -// Computed: true, -// -// 4. Optional AND Computed - the provider or user can provide a value; -// use this combination if you are using Default -// -// Optional: true, -// Computed: true, -// -// You will typically find arguments in the input struct -// (e.g., CreateDBInstanceInput) for the create operation. Sometimes -// they are only in the input struct (e.g., ModifyDBInstanceInput) for -// the modify operation. -// -// For more about schema options, visit -// https://developer.hashicorp.com/terraform/plugin/framework/handling-data/schemas?page=schemas func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -142,15 +76,6 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res // Map name to TLSInspectionConfigurationName "name": schema.StringAttribute{ Required: true, - // TIP: ==== PLAN MODIFIERS ==== - // Plan modifiers were introduced with Plugin-Framework to provide a mechanism - // for adjusting planned changes prior to apply. The planmodifier subpackage - // provides built-in modifiers for many common use cases such as - // requiring replacement on a value change ("ForceNew: true" in Plugin-SDK - // resources). - // - // See more: - // https://developer.hashicorp.com/terraform/plugin/framework/resources/plan-modification PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), }, @@ -217,23 +142,6 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, - - // NestedObject: schema.NestedBlockObject{ - // Attributes: map[string]schema.Attribute{ - // "certificate_arn": schema.StringAttribute{ - // Computed: true, - // }, - // "certificate_serial": schema.StringAttribute{ - // Computed: true, - // }, - // "status": schema.StringAttribute{ - // Computed: true, - // }, - // "status_message": schema.StringAttribute{ - // Computed: true, - // }, - // }, - // }, }, "encryption_configuration": schema.ListNestedBlock{ NestedObject: schema.NestedBlockObject{ @@ -347,33 +255,6 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, - // "complex_argument": schema.ListNestedBlock{ - // // TIP: ==== LIST VALIDATORS ==== - // // List and set validators take the place of MaxItems and MinItems in - // // Plugin-Framework based resources. Use listvalidator.SizeAtLeast(1) to - // // make a nested object required. Similar to Plugin-SDK, complex objects - // // can be represented as lists or sets with listvalidator.SizeAtMost(1). - // // - // // For a complete mapping of Plugin-SDK to Plugin-Framework schema fields, - // // see: - // // https://developer.hashicorp.com/terraform/plugin/framework/migrating/attributes-blocks/blocks - // Validators: []validator.List{ - // listvalidator.SizeAtMost(1), - // }, - // NestedObject: schema.NestedBlockObject{ - // Attributes: map[string]schema.Attribute{ - // "nested_required": schema.StringAttribute{ - // Required: true, - // }, - // "nested_computed": schema.StringAttribute{ - // Computed: true, - // PlanModifiers: []planmodifier.String{ - // stringplanmodifier.UseStateForUnknown(), - // }, - // }, - // }, - // }, - // }, "timeouts": timeouts.Block(ctx, timeouts.Opts{ Create: true, Update: true, @@ -384,31 +265,14 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res } func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - // TIP: ==== RESOURCE CREATE ==== - // Generally, the Create function should do the following things. Make - // sure there is a good reason if you don't do one of these. - // - // 1. Get a client connection to the relevant service - // 2. Fetch the plan - // 3. Populate a create input structure - // 4. Call the AWS create/put function - // 5. Using the output from the create function, set the minimum arguments - // and attributes for the Read function to work, as well as any computed - // only attributes. - // 6. Use a waiter to wait for create to complete - // 7. Save the request plan to response state - - // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - // TIP: -- 2. Fetch the plan var plan resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) if resp.Diagnostics.HasError() { return } - // TIP: -- 3. Populate a create input structure in := &networkfirewall.CreateTLSInspectionConfigurationInput{ // NOTE: Name is mandatory TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), @@ -419,23 +283,17 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res in.Description = aws.String(plan.Description.ValueString()) } - // Complex arguments if !plan.TLSInspectionConfiguration.IsNull() { - // TIP: Use an expander to assign a complex argument. The elements must be - // deserialized into the appropriate struct before being passed to the expander. var tfList []tlsInspectionConfigurationData resp.Diagnostics.Append(plan.TLSInspectionConfiguration.ElementsAs(ctx, &tfList, false)...) if resp.Diagnostics.HasError() { return } - // in.TLSInspectionConfiguration = expandComplexArgument(tfList) in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(ctx, tfList) } if !plan.EncryptionConfiguration.IsNull() { - // TIP: Use an expander to assign a complex argument. The elements must be - // deserialized into the appropriate struct before being passed to the expander. var tfList []encryptionConfigurationData resp.Diagnostics.Append(plan.EncryptionConfiguration.ElementsAs(ctx, &tfList, false)...) if resp.Diagnostics.HasError() { @@ -445,11 +303,8 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) } - // TIP: -- 4. Call the AWS create function out, err := conn.CreateTLSInspectionConfiguration(in) if err != nil { - // TIP: Since ID has not been set yet, you cannot use plan.ID.String() - // in error messages at this point. resp.Diagnostics.AddError( create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), err), err.Error(), @@ -464,10 +319,8 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res return } - // TIP: -- 5. Using the output from the create function, set the minimum attributes - // Output consists only of TLSInspectionConfigurationResponse plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - // Set ID to ARN since ID value is not used for Describe, Update, Delete or List calls + // Set ID to ARN since ID value is not used for describe, update, delete or list API calls plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) @@ -483,7 +336,6 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res resp.Diagnostics.Append(flex.Flatten(ctx, readComputed.TLSInspectionConfigurationResponse.Certificates, &plan.Certificates)...) - // TIP: -- 6. Use a waiter to wait for create to complete createTimeout := r.CreateTimeout(ctx, plan.Timeouts) _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ARN.ValueString(), createTimeout) if err != nil { @@ -494,7 +346,6 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res return } - // TIP: -- 7. Save the request plan to response state resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) } @@ -536,18 +387,6 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou return } - // TIP: -- 5. Set the arguments and attributes - // - // For simple data types (i.e., schema.StringAttribute, schema.BoolAttribute, - // schema.Int64Attribute, and schema.Float64Attribue), simply setting the - // appropriate data struct field is sufficient. The flex package implements - // helpers for converting between Go and Plugin-Framework types seamlessly. No - // error or nil checking is necessary. - // - // However, there are some situations where more handling is needed such as - // complex data types (e.g., schema.ListAttribute, schema.SetAttribute). In - // these cases the flatten function may have a diagnostics return value, which - // should be appended to resp.Diagnostics. state.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) state.Description = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.Description) @@ -588,43 +427,12 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou state.TLSInspectionConfiguration = tlsInspectionConfiguration fmt.Printf("diags for tls: %v\n", resp.Diagnostics) - // TIP: Setting a complex type. - // complexArgument, d := flattenComplexArgument(ctx, out.ComplexArgument) - // resp.Diagnostics.Append(d...) - // state.ComplexArgument = complexArgument - - // TIP: -- 6. Set the state resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) - - // Print diagnostics - } func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - // TIP: ==== RESOURCE UPDATE ==== - // Not all resources have Update functions. There are a few reasons: - // a. The AWS API does not support changing a resource - // b. All arguments have RequiresReplace() plan modifiers - // c. The AWS API uses a create call to modify an existing resource - // - // In the cases of a. and b., the resource will not have an update method - // defined. In the case of c., Update and Create can be refactored to call - // the same underlying function. - // - // The rest of the time, there should be an Update function and it should - // do the following things. Make sure there is a good reason if you don't - // do one of these. - // - // 1. Get a client connection to the relevant service - // 2. Fetch the plan and state - // 3. Populate a modify input structure and check for changes - // 4. Call the AWS modify/update function - // 5. Use a waiter to wait for update to complete - // 6. Save the request plan to response state - // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - // TIP: -- 2. Fetch the plan var plan, state resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) resp.Diagnostics.Append(req.State.Get(ctx, &state)...) @@ -632,35 +440,19 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res return } - // TIP: -- 3. Populate a modify input structure and check for changes if !plan.Description.Equal(state.Description) || !plan.TLSInspectionConfiguration.Equal(state.TLSInspectionConfiguration) || !plan.EncryptionConfiguration.Equal(state.EncryptionConfiguration) { in := &networkfirewall.UpdateTLSInspectionConfigurationInput{ - // TIP: Mandatory or fields that will always be present can be set when - // you create the Input structure. (Replace these with real fields.) TLSInspectionConfigurationArn: aws.String(plan.ARN.ValueString()), TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), UpdateToken: aws.String(plan.UpdateToken.ValueString()), } if !plan.Description.IsNull() { - // TIP: Optional fields should be set based on whether or not they are - // used. in.Description = aws.String(plan.Description.ValueString()) } - // if !plan.ComplexArgument.IsNull() { - // // TIP: Use an expander to assign a complex argument. The elements must be - // // deserialized into the appropriate struct before being passed to the expander. - // var tfList []complexArgumentData - // resp.Diagnostics.Append(plan.ComplexArgument.ElementsAs(ctx, &tfList, false)...) - // if resp.Diagnostics.HasError() { - // return - // } - - // in.ComplexArgument = expandComplexArgument(tfList) - // } if !plan.TLSInspectionConfiguration.IsNull() { var tfList []tlsInspectionConfigurationData @@ -681,7 +473,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) } - // TIP: -- 4. Call the AWS modify/update function out, err := conn.UpdateTLSInspectionConfigurationWithContext(ctx, in) if err != nil { resp.Diagnostics.AddError( @@ -698,7 +489,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res return } - // TIP: Using the output from the update function, re-set any computed attributes plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) @@ -708,7 +498,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res plan.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) } - // TIP: -- 5. Use a waiter to wait for update to complete updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) _, err := waitTLSInspectionConfigurationUpdated(ctx, conn, plan.ARN.ValueString(), updateTimeout) if err != nil { @@ -719,7 +508,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res return } - // TIP: -- 6. Save the request plan to response state resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) } @@ -732,15 +520,11 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res return } - // TIP: -- 3. Populate a delete input structure in := &networkfirewall.DeleteTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(state.ARN.ValueString()), } - // TIP: -- 4. Call the AWS delete function _, err := conn.DeleteTLSInspectionConfigurationWithContext(ctx, in) - // TIP: On rare occassions, the API returns a not found error after deleting a - // resource. If that happens, we don't want it to show up as an error. if err != nil { if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { return @@ -752,7 +536,6 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res return } - // TIP: -- 5. Use a waiter to wait for delete to complete deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) _, err = waitTLSInspectionConfigurationDeleted(ctx, conn, state.ARN.ValueString(), deleteTimeout) if err != nil { @@ -767,13 +550,6 @@ func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req res } } -// TIP: ==== TERRAFORM IMPORTING ==== -// If Read can get all the information it needs from the Identifier -// (i.e., path.Root("id")), you can use the PassthroughID importer. Otherwise, -// you'll need a custom import function. -// -// See more: -// https://developer.hashicorp.com/terraform/plugin/framework/resources/import func (r *resourceTLSInspectionConfiguration) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } @@ -789,19 +565,6 @@ const ( statusUpdated = "Updated" ) -// TIP: ==== WAITERS ==== -// Some resources of some services have waiters provided by the AWS API. -// Unless they do not work properly, use them rather than defining new ones -// here. -// -// Sometimes we define the wait, status, and find functions in separate -// files, wait.go, status.go, and find.go. Follow the pattern set out in the -// service and define these where it makes the most sense. -// -// If these functions are used in the _test.go file, they will need to be -// exported (i.e., capitalized). -// -// You will need to adjust the parameters and names to fit the service. func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{}, @@ -820,10 +583,6 @@ func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfir return nil, err } -// TIP: It is easier to determine whether a resource is updated for some -// resources than others. The best case is a status flag that tells you when -// the update has been fully realized. Other times, you can check to see if a -// key resource argument is updated to a new value or not. func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{statusChangePending}, @@ -842,8 +601,6 @@ func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfir return nil, err } -// TIP: A deleted waiter is almost like a backwards created waiter. There may -// be additional pending states, however. func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{networkfirewall.ResourceStatusDeleting, networkfirewall.ResourceStatusActive}, @@ -860,13 +617,6 @@ func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfir return nil, err } -// TIP: ==== STATUS ==== -// The status function can return an actual status when that field is -// available from the API (e.g., out.Status). Otherwise, you can use custom -// statuses to communicate the states of the resource. -// -// Waiters consume the values returned by status functions. Design status so -// that it can be reused by a create, update, and delete waiter, if possible. func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, arn) @@ -882,11 +632,6 @@ func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall } } -// TIP: ==== FINDERS ==== -// The find function is not strictly necessary. You could do the API -// request from the status function. However, we have found that find often -// comes in handy in other places besides the status function. As a result, it -// is good practice to define it separately. func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { in := &networkfirewall.DescribeTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(arn), @@ -935,38 +680,6 @@ func findTLSInspectionConfigurationByID(ctx context.Context, conn *networkfirewa return out, nil } -// TIP: ==== FLEX ==== -// Flatteners and expanders ("flex" functions) help handle complex data -// types. Flatteners take an API data type and return the equivalent Plugin-Framework -// type. In other words, flatteners translate from AWS -> Terraform. -// -// On the other hand, expanders take a Terraform data structure and return -// something that you can send to the AWS API. In other words, expanders -// translate from Terraform -> AWS. -// -// See more: -// https://hashicorp.github.io/terraform-provider-aws/data-handling-and-conversion/ -// func flattenComplexArgument(ctx context.Context, apiObject *awstypes.ComplexArgument) (types.List, diag.Diagnostics) { -// var diags diag.Diagnostics -// elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} - -// if apiObject == nil { -// return types.ListNull(elemType), diags -// } - -// obj := map[string]attr.Value{ -// "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), -// "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), -// } -// objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) -// diags.Append(d...) - -// listVal, d := types.ListValue(elemType, []attr.Value{objVal}) -// diags.Append(d...) - -// return listVal, diags -// } - func flattenTLSInspectionConfiguration(ctx context.Context, tlsInspectionConfiguration *networkfirewall.TLSInspectionConfiguration) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: tlsInspectionConfigurationAttrTypes} @@ -991,28 +704,6 @@ func flattenTLSInspectionConfiguration(ctx context.Context, tlsInspectionConfigu } -// func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfiguration *networkfirewall.EncryptionConfiguration) (types.List, diag.Diagnostics) { -// var diags diag.Diagnostics -// elemType := types.ObjectType{AttrTypes: encryptionConfigurationAttrTypes} - -// if encryptionConfiguration == nil { -// return types.ListNull(elemType), diags -// } - -// obj := map[string]attr.Value{ -// "key_id": flex.StringToFramework(ctx, encryptionConfiguration.KeyId), -// "type": flex.StringToFramework(ctx, encryptionConfiguration.Type), -// } -// objVal, d := types.ObjectValue(encryptionConfigurationAttrTypes, obj) -// diags.Append(d...) - -// listVal, d := types.ListValue(elemType, []attr.Value{objVal}) -// diags.Append(d...) - -// return listVal, diags - -// } - func flattenServerCertificateConfigurations(ctx context.Context, serverCertificateConfigurations []*networkfirewall.ServerCertificateConfiguration) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes} @@ -1299,62 +990,6 @@ func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfigurat } -// TIP: Often the AWS API will return a slice of structures in response to a -// request for information. Sometimes you will have set criteria (e.g., the ID) -// that means you'll get back a one-length slice. This plural function works -// brilliantly for that situation too. -// func flattenComplexArguments(ctx context.Context, apiObjects []*awstypes.ComplexArgument) (types.List, diag.Diagnostics) { -// var diags diag.Diagnostics -// elemType := types.ObjectType{AttrTypes: complexArgumentAttrTypes} - -// if len(apiObjects) == 0 { -// return types.ListNull(elemType), diags -// } - -// elems := []attr.Value{} -// for _, apiObject := range apiObjects { -// if apiObject == nil { -// continue -// } - -// obj := map[string]attr.Value{ -// "nested_required": flex.StringValueToFramework(ctx, apiObject.NestedRequired), -// "nested_optional": flex.StringValueToFramework(ctx, apiObject.NestedOptional), -// } -// objVal, d := types.ObjectValue(complexArgumentAttrTypes, obj) -// diags.Append(d...) - -// elems = append(elems, objVal) -// } - -// listVal, d := types.ListValue(elemType, elems) -// diags.Append(d...) - -// return listVal, diags -// } - -// TIP: Remember, as mentioned above, expanders take a Terraform data structure -// and return something that you can send to the AWS API. In other words, -// expanders translate from Terraform -> AWS. -// -// See more: -// https://hashicorp.github.io/terraform-provider-aws/data-handling-and-conversion/ -// func expandComplexArgument(tfList []complexArgumentData) *awstypes.ComplexArgument { -// if len(tfList) == 0 { -// return nil -// } - -// tfObj := tfList[0] -// apiObject := &awstypes.ComplexArgument{ -// NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), -// } -// if !tfObj.NestedOptional.IsNull() { -// apiObject.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) -// } - -// return apiObject -// } - // TODO: add note explaining why not using existing expandEncryptionConfiguration() func expandTLSEncryptionConfiguration(tfList []encryptionConfigurationData) *networkfirewall.EncryptionConfiguration { if len(tfList) == 0 { @@ -1516,66 +1151,6 @@ func expandSourceDestinations(ctx context.Context, tfList []sourceDestinationDat return apiObject } -// func expandTLSCertificateData(tfObj certificatesData) *networkfirewall.TlsCertificateData { -// item := &networkfirewall.TlsCertificateData{ -// CertificateArn: aws.String(tfObj.CertificateArn.ValueString()), -// CertificateSerial: aws.String(tfObj.CertificateSerial.ValueString()), -// Status: aws.String(tfObj.Status.ValueString()), -// StatusMessage: aws.String(tfObj.StatusMessage.ValueString()), -// } -// return item -// } - -// TIP: Even when you have a list with max length of 1, this plural function -// works brilliantly. However, if the AWS API takes a structure rather than a -// slice of structures, you will not need it. -// func expandComplexArguments(tfList []complexArgumentData) []*networkfirewall.ComplexArgument { -// // TIP: The AWS API can be picky about whether you send a nil or zero- -// // length for an argument that should be cleared. For example, in some -// // cases, if you send a nil value, the AWS API interprets that as "make no -// // changes" when what you want to say is "remove everything." Sometimes -// // using a zero-length list will cause an error. -// // -// // As a result, here are two options. Usually, option 1, nil, will work as -// // expected, clearing the field. But, test going from something to nothing -// // to make sure it works. If not, try the second option. -// // TIP: Option 1: Returning nil for zero-length list -// if len(tfList) == 0 { -// return nil -// } -// var apiObject []*awstypes.ComplexArgument -// // TIP: Option 2: Return zero-length list for zero-length list. If option 1 does -// // not work, after testing going from something to nothing (if that is -// // possible), uncomment out the next line and remove option 1. -// // -// // apiObject := make([]*networkfirewall.ComplexArgument, 0) - -// for _, tfObj := range tfList { -// item := &networkfirewall.ComplexArgument{ -// NestedRequired: aws.String(tfObj.NestedRequired.ValueString()), -// } -// if !tfObj.NestedOptional.IsNull() { -// item.NestedOptional = aws.String(tfObj.NestedOptional.ValueString()) -// } - -// apiObject = append(apiObject, item) -// } - -// return apiObject -// } - -// TIP: ==== DATA STRUCTURES ==== -// With Terraform Plugin-Framework configurations are deserialized into -// Go types, providing type safety without the need for type assertions. -// These structs should match the schema definition exactly, and the `tfsdk` -// tag value should match the attribute name. -// -// Nested objects are represented in their own data struct. These will -// also have a corresponding attribute type mapping for use inside flex -// functions. -// -// See more: -// https://developer.hashicorp.com/terraform/plugin/framework/handling-data/accessing-values type resourceTLSInspectionConfigurationData struct { ARN types.String `tfsdk:"arn"` EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` @@ -1616,11 +1191,6 @@ type serverCertificateConfigurationsData struct { ServerCertificates types.List `tfsdk:"server_certificates"` } -// type complexArgumentData struct { -// NestedRequired types.String `tfsdk:"nested_required"` -// NestedOptional types.String `tfsdk:"nested_optional"` -// } - type scopeData struct { DestinationPorts types.List `tfsdk:"destination_ports"` Destinations types.List `tfsdk:"destinations"` @@ -1647,8 +1217,6 @@ type serverCertificatesData struct { ResourceARN types.String `tfsdk:"resource_arn"` } -////////////// - var certificatesAttrTypes = map[string]attr.Type{ "certificate_arn": types.StringType, "certificate_serial": types.StringType, @@ -1656,11 +1224,6 @@ var certificatesAttrTypes = map[string]attr.Type{ "status_message": types.StringType, } -// var complexArgumentAttrTypes = map[string]attr.Type{ -// "nested_required": types.StringType, -// "nested_optional": types.StringType, -// } - var encryptionConfigurationAttrTypes = map[string]attr.Type{ "type": types.StringType, "key_id": types.StringType, @@ -1668,7 +1231,6 @@ var encryptionConfigurationAttrTypes = map[string]attr.Type{ var tlsInspectionConfigurationAttrTypes = map[string]attr.Type{ "server_certificate_configurations": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes}}, - //"server_certificate_configurations": fwtypes.ListNestedObjectValueOf[serverCertificateConfigurationAttrTypes], } var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ From 8d04d87567b8625463bf5af63aa563ddb2d5ca94 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 19 Jan 2024 17:19:47 -0500 Subject: [PATCH 15/68] Cleanup: copywrite headers --- .../service/networkfirewall/tls_inspection_configuration.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 232e952b141..bbed101d242 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package networkfirewall import ( From a4cb3ad402119425d2c778611e810fb1ff9ed42c Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 9 Feb 2024 15:09:01 -0500 Subject: [PATCH 16/68] Fix missing certificates, CA cert data --- .../tls_inspection_configuration.go | 199 +++++++++--------- .../tls_inspection_configuration_test.go | 186 +++++++++++++++- 2 files changed, 280 insertions(+), 105 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index bbed101d242..4a046149159 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -6,7 +6,6 @@ package networkfirewall import ( "context" "errors" - "fmt" "time" "github.com/aws/aws-sdk-go-v2/aws" @@ -24,7 +23,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" @@ -75,6 +73,29 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res "description": schema.StringAttribute{ Optional: true, }, + "certificate_authority": schema.ListAttribute{ + Computed: true, + ElementType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "certificate_arn": types.StringType, + "certificate_serial": types.StringType, + "status": types.StringType, + "status_message": types.StringType, + }, + }, + }, + "certificates": schema.ListAttribute{ + CustomType: fwtypes.NewListNestedObjectTypeOf[certificatesData](ctx), + Computed: true, + ElementType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "certificate_arn": types.StringType, + "certificate_serial": types.StringType, + "status": types.StringType, + "status_message": types.StringType, + }, + }, + }, "id": framework.IDAttribute(), // Map name to TLSInspectionConfigurationName "name": schema.StringAttribute{ @@ -85,9 +106,6 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, "last_modified_time": schema.StringAttribute{ Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, }, "number_of_associations": schema.Int64Attribute{ Computed: true, @@ -103,49 +121,9 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, "update_token": schema.StringAttribute{ Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, }, }, Blocks: map[string]schema.Block{ - "certificate_authority": schema.ListNestedBlock{ - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "certificate_arn": schema.StringAttribute{ - Computed: true, - }, - "certificate_serial": schema.StringAttribute{ - Computed: true, - }, - "status": schema.StringAttribute{ - Computed: true, - }, - "status_message": schema.StringAttribute{ - Computed: true, - }, - }, - }, - }, - "certificates": schema.ListNestedBlock{ - CustomType: fwtypes.NewListNestedObjectTypeOf[certificatesData](ctx), - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "certificate_arn": schema.StringAttribute{ - Computed: true, - }, - "certificate_serial": schema.StringAttribute{ - Computed: true, - }, - "status": schema.StringAttribute{ - Computed: true, - }, - "status_message": schema.StringAttribute{ - Computed: true, - }, - }, - }, - }, "encryption_configuration": schema.ListNestedBlock{ NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ @@ -314,31 +292,19 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res ) return } - if out == nil || out.TLSInspectionConfigurationResponse == nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), nil), - errors.New("empty output").Error(), - ) - return - } + // if out == nil || out.TLSInspectionConfigurationResponse == nil { + // resp.Diagnostics.AddError( + // create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), nil), + // errors.New("empty output").Error(), + // ) + // return + // } plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) // Set ID to ARN since ID value is not used for describe, update, delete or list API calls plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) - // Read to get computed attributes not returned from create - readComputed, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, plan.ARN.ValueString()) - - fmt.Println("Output from readComputed: ", readComputed) - - // Set computed attributes - plan.LastModifiedTime = flex.StringValueToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) - plan.NumberOfAssociations = flex.Int64ToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.NumberOfAssociations) - plan.Status = flex.StringToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) - - resp.Diagnostics.Append(flex.Flatten(ctx, readComputed.TLSInspectionConfigurationResponse.Certificates, &plan.Certificates)...) - createTimeout := r.CreateTimeout(ctx, plan.Timeouts) _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ARN.ValueString(), createTimeout) if err != nil { @@ -349,35 +315,33 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res return } + // Read to get computed attributes not returned from create + readComputed, _ := findTLSInspectionConfigurationByNameAndARN(ctx, conn, plan.ARN.ValueString()) + + // Set computed attributes + plan.LastModifiedTime = flex.StringValueToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) + plan.NumberOfAssociations = flex.Int64ToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.NumberOfAssociations) + plan.Status = flex.StringToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) + + resp.Diagnostics.Append(flex.Flatten(ctx, readComputed.TLSInspectionConfigurationResponse.Certificates, &plan.Certificates)...) + + certificateAuthority, d := flattenTLSCertificate(ctx, readComputed.TLSInspectionConfigurationResponse.CertificateAuthority) + resp.Diagnostics.Append(d...) + plan.CertificateAuthority = certificateAuthority + resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) } func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - // TIP: ==== RESOURCE READ ==== - // Generally, the Read function should do the following things. Make - // sure there is a good reason if you don't do one of these. - // - // 1. Get a client connection to the relevant service - // 2. Fetch the state - // 3. Get the resource from AWS - // 4. Remove resource from state if it is not found - // 5. Set the arguments and attributes - // 6. Set the state - - // TIP: -- 1. Get a client connection to the relevant service conn := r.Meta().NetworkFirewallConn(ctx) - // TIP: -- 2. Fetch the state var state resourceTLSInspectionConfigurationData resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { return } - // TIP: -- 3. Get the resource from AWS using an API Get, List, or Describe- - // type function, or, better yet, using a finder. out, err := findTLSInspectionConfigurationByID(ctx, conn, state.ID.ValueString()) - // TIP: -- 4. Remove resource from state if it is not found if tfresource.NotFound(err) { resp.State.RemoveResource(ctx) return @@ -406,29 +370,19 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou encryptionConfiguration, d := flattenTLSEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) resp.Diagnostics.Append(d...) state.EncryptionConfiguration = encryptionConfiguration - fmt.Printf("diags for encryption config: %v\n", resp.Diagnostics) certificateAuthority, d := flattenTLSCertificate(ctx, out.TLSInspectionConfigurationResponse.CertificateAuthority) resp.Diagnostics.Append(d...) state.CertificateAuthority = certificateAuthority - fmt.Printf("diags for certificate authority: %v\n", resp.Diagnostics) - - // certificates, d := flattenCertificates(ctx, out.TLSInspectionConfigurationResponse.Certificates) - // resp.Diagnostics.Append(d...) - // state.Certificates = certificates - // fmt.Printf("diags for certificates: %v\n", resp.Diagnostics) resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfigurationResponse.Certificates, &state.Certificates)...) - fmt.Printf("Attempting to flatten Certificates: %v\n", resp.Diagnostics) resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfiguration, &state.TLSInspectionConfiguration)...) - fmt.Printf("Attempting to flatten TLSInspectionConfiguration: %v\n", resp.Diagnostics) tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) resp.Diagnostics.Append(d...) state.TLSInspectionConfiguration = tlsInspectionConfiguration - fmt.Printf("diags for tls: %v\n", resp.Diagnostics) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } @@ -450,7 +404,7 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res in := &networkfirewall.UpdateTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(plan.ARN.ValueString()), TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), - UpdateToken: aws.String(plan.UpdateToken.ValueString()), + UpdateToken: aws.String(state.UpdateToken.ValueString()), } if !plan.Description.IsNull() { @@ -493,12 +447,27 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res } plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) - + // Set ID to ARN since ID value is not used for describe, update, delete or list API calls + plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) plan.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) - plan.NumberOfAssociations = flex.Int64ToFramework(ctx, out.TLSInspectionConfigurationResponse.NumberOfAssociations) plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) plan.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) + + encryptionConfiguration, d := flattenTLSEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) + resp.Diagnostics.Append(d...) + plan.EncryptionConfiguration = encryptionConfiguration + + // Update does not certificates and CA, so read to backfill the missing attributes + // NOTE: number of associations should be returned according to the API docs, but isn't! + readComputed, _ := findTLSInspectionConfigurationByNameAndARN(ctx, conn, plan.ARN.ValueString()) + plan.NumberOfAssociations = flex.Int64ToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.NumberOfAssociations) + + // Complex types + certificateAuthority, d := flattenTLSCertificate(ctx, readComputed.TLSInspectionConfigurationResponse.CertificateAuthority) + resp.Diagnostics.Append(d...) + plan.CertificateAuthority = certificateAuthority + + resp.Diagnostics.Append(flex.Flatten(ctx, readComputed.TLSInspectionConfigurationResponse.Certificates, &plan.Certificates)...) } updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) @@ -570,12 +539,12 @@ const ( func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{}, + Pending: []string{statusChangePending}, Target: []string{networkfirewall.ResourceStatusActive}, - Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), + Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), Timeout: timeout, NotFoundChecks: 20, - ContinuousTargetOccurence: 2, + ContinuousTargetOccurence: 5, } outputRaw, err := stateConf.WaitForStateContext(ctx) @@ -586,11 +555,37 @@ func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfir return nil, err } +func statusTLSInspectionConfigurationCertificates(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, arn) + if tfresource.NotFound(err) { + return nil, "", nil + } + + if err != nil { + return nil, "", err + } + + certificates := out.TLSInspectionConfigurationResponse.Certificates + certificateAuthority := out.TLSInspectionConfigurationResponse.CertificateAuthority + + // The API does not immediately return data for certificates and certificate authority even when the resource status is "ACTIVE", + // which causes unexpected diffs when reading. This sets the status to "PENDING" until either the certificates or the certificate + // authority is populated (the API will always return at least one of the two) + if aws.ToString(out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) == networkfirewall.ResourceStatusActive && + (certificates != nil || certificateAuthority != nil) { + return out, aws.ToString(out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus), nil + } else { + return out, statusChangePending, nil + } + } +} + func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { stateConf := &retry.StateChangeConf{ Pending: []string{statusChangePending}, Target: []string{networkfirewall.ResourceStatusActive}, - Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), + Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), Timeout: timeout, NotFoundChecks: 20, ContinuousTargetOccurence: 2, @@ -789,7 +784,6 @@ func flattenServerCertificates(ctx context.Context, serverCertificateList []*net listVal, d := types.ListValue(elemType, elems) diags.Append(d...) - fmt.Printf("diags from flattenServerCertificates: %v\n", diags) return listVal, diags } @@ -1122,8 +1116,6 @@ func expandScopes(ctx context.Context, tfList []scopeData) []*networkfirewall.Se apiObject = append(apiObject, item) } - fmt.Printf("diags: %v\n", diags) - return apiObject } @@ -1155,9 +1147,8 @@ func expandSourceDestinations(ctx context.Context, tfList []sourceDestinationDat } type resourceTLSInspectionConfigurationData struct { - ARN types.String `tfsdk:"arn"` - EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` - // Certificates types.List `tfsdk:"certificates"` + ARN types.String `tfsdk:"arn"` + EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` Certificates fwtypes.ListNestedObjectValueOf[certificatesData] `tfsdk:"certificates"` CertificateAuthority types.List `tfsdk:"certificate_authority"` Description types.String `tfsdk:"description"` diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index cc7a7ed7dc2..ccad7bafc90 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -128,6 +128,106 @@ import ( // NOTE: acceptance tests require environment variable ACM_CERTIFICATE_ARN // to be set and the ACM certificate to be validated during testing. +func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput + certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") + if certificateArn == "" { + t.Skipf("Environment variable %s is not set, skipping test", certificateArn) + } + caCertificateArn := os.Getenv("ACM_CA_CERTIFICATE_ARN") + if certificateArn == "" { + t.Skipf("Environment variable %s is not set, skipping test", caCertificateArn) + } + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateArn, caCertificateArn), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ + "key_id": "AWS_OWNED_KMS_KEY", + "type": "AWS_OWNED_KMS_KEY", + }), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", caCertificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateArn, caCertificateArn), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ + "key_id": "AWS_OWNED_KMS_KEY", + "type": "AWS_OWNED_KMS_KEY", + }), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "8080"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "1024"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65534"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", caCertificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "REJECT"), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -243,7 +343,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), - // resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), + resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, @@ -434,6 +534,90 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name stri // } // } +func testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateARN, ca string) string { + return fmt.Sprintf(` +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + description = "test" + encryption_configuration { + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = %[3]q + check_certificate_revocation_status { + revoked_status_action = "REJECT" + unknown_status_action = "PASS" + } + server_certificates { + resource_arn = %[2]q + } + scopes { + protocols = [ 6 ] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +`, rName, certificateARN, ca) +} + +func testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateARN, ca string) string { + return fmt.Sprintf(` +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + description = "test" + encryption_configuration { + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = %[3]q + check_certificate_revocation_status { + revoked_status_action = "PASS" + unknown_status_action = "REJECT" + } + server_certificates { + resource_arn = %[2]q + } + scopes { + protocols = [ 6 ] + destination_ports { + from_port = 443 + to_port = 8080 + } + destinations { + address_definition = "10.0.0.0/8" + } + source_ports { + from_port = 1024 + to_port = 65534 + } + sources { + address_definition = "10.0.0.0/8" + } + } + } + } +} +`, rName, certificateARN, ca) +} + func testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateARN string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { From 5c248438fed89a70d60f04273dd8edbb86754bd1 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:30:50 -0500 Subject: [PATCH 17/68] Remove SDKv2, change Create to run with ctx, run linters --- .../tls_inspection_configuration.go | 7 +- .../tls_inspection_configuration_test.go | 80 +++++++++---------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 4a046149159..78565c32362 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -9,9 +9,9 @@ import ( "time" "github.com/aws/aws-sdk-go-v2/aws" - awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/aws/aws-sdk-go/service/networkfirewall" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" // "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" @@ -27,7 +27,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-provider-aws/internal/create" - "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/framework" "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" @@ -137,7 +136,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res Computed: true, Default: stringdefault.StaticString("AWS_OWNED_KMS_KEY"), Validators: []validator.String{ - enum.FrameworkValidate[awstypes.EncryptionType](), + stringvalidator.OneOf(networkfirewall.EncryptionTypeAwsOwnedKmsKey, networkfirewall.EncryptionTypeCustomerKms), }, }, }, @@ -284,7 +283,7 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) } - out, err := conn.CreateTLSInspectionConfiguration(in) + out, err := conn.CreateTLSInspectionConfigurationWithContext(ctx, in) if err != nil { resp.Diagnostics.AddError( create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), err), diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index ccad7bafc90..fb1c4fc98d6 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -537,34 +537,34 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name stri func testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateARN, ca string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q + name = %[1]q description = "test" encryption_configuration { key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { server_certificate_configurations { certificate_authority_arn = %[3]q check_certificate_revocation_status { - revoked_status_action = "REJECT" - unknown_status_action = "PASS" + revoked_status_action = "REJECT" + unknown_status_action = "PASS" } server_certificates { resource_arn = %[2]q } scopes { - protocols = [ 6 ] + protocols = [6] destination_ports { - from_port = 443 - to_port = 443 + from_port = 443 + to_port = 443 } destinations { address_definition = "0.0.0.0/0" - } + } source_ports { from_port = 0 - to_port = 65535 + to_port = 65535 } sources { address_definition = "0.0.0.0/0" @@ -579,34 +579,34 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { func testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateARN, ca string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q + name = %[1]q description = "test" encryption_configuration { key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { server_certificate_configurations { certificate_authority_arn = %[3]q check_certificate_revocation_status { - revoked_status_action = "PASS" - unknown_status_action = "REJECT" + revoked_status_action = "PASS" + unknown_status_action = "REJECT" } server_certificates { resource_arn = %[2]q } scopes { - protocols = [ 6 ] + protocols = [6] destination_ports { - from_port = 443 - to_port = 8080 + from_port = 443 + to_port = 8080 } destinations { address_definition = "10.0.0.0/8" - } + } source_ports { from_port = 1024 - to_port = 65534 + to_port = 65534 } sources { address_definition = "10.0.0.0/8" @@ -621,11 +621,11 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { func testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateARN string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q + name = %[1]q description = "test" encryption_configuration { key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { server_certificate_configurations { @@ -633,17 +633,17 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { resource_arn = %[2]q } scopes { - protocols = [ 6 ] + protocols = [6] destination_ports { - from_port = 443 - to_port = 443 + from_port = 443 + to_port = 443 } destinations { address_definition = "0.0.0.0/0" - } + } source_ports { from_port = 0 - to_port = 65535 + to_port = 65535 } sources { address_definition = "0.0.0.0/0" @@ -667,11 +667,11 @@ resource "aws_kms_key" "test" { func testAccTLSInspectionConfigurationConfig_ingressWithEncryptionConfiguration(rName, certificateARN string) string { return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName), fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q + name = %[1]q description = "test" encryption_configuration { key_id = aws_kms_key.test.arn - type = "CUSTOMER_KMS" + type = "CUSTOMER_KMS" } tls_inspection_configuration { server_certificate_configurations { @@ -679,20 +679,20 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { resource_arn = %[2]q } scopes { - protocols = [ 6 ] + protocols = [6] destination_ports { from_port = 443 - to_port = 443 + to_port = 443 } destinations { - address_definition = "0.0.0.0/0" - } + address_definition = "0.0.0.0/0" + } source_ports { - from_port = 0 - to_port = 65535 + from_port = 0 + to_port = 65535 } sources { - address_definition = "0.0.0.0/0" + address_definition = "0.0.0.0/0" } } } @@ -710,11 +710,11 @@ resource "aws_acm_certificate" "test" { } resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q + name = %[1]q description = "test" encryption_configuration { key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { server_certificate_configurations { @@ -724,17 +724,17 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { unknown_status_action = "PASS" } scopes { - protocols = [ 6 ] + protocols = [6] destination_ports { from_port = 443 - to_port = 443 + to_port = 443 } destinations { address_definition = "0.0.0.0/0" - } + } source_ports { from_port = 0 - to_port = 65535 + to_port = 65535 } sources { address_definition = "0.0.0.0/0" From 8c4d1ffacfd11822ca0251b720310aee4bc8dc35 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:42:38 -0500 Subject: [PATCH 18/68] Add docs --- .../tls_inspection_configuration_test.go | 103 +---- ...tls_inspection_configuration.html.markdown | 366 ++++++++++++++++++ 2 files changed, 367 insertions(+), 102 deletions(-) create mode 100644 website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index fb1c4fc98d6..ecb8ebd14f4 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -4,18 +4,6 @@ package networkfirewall_test import ( - // TIP: ==== IMPORTS ==== - // This is a common set of imports but not customized to your code since - // your code hasn't been written yet. Make sure you, your IDE, or - // goimports -w fixes these imports. - // - // The provider linter wants your imports to be in two groups: first, - // standard library (i.e., "fmt" or "strings"), second, everything else. - // - // Also, AWS Go SDK v2 may handle nested structures differently than v1, - // using the services/networkfirewall/types package. If so, you'll - // need to import types and reference the nested types, e.g., as - // types.. "context" "errors" "fmt" @@ -32,99 +20,10 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/errs" - "github.com/hashicorp/terraform-provider-aws/names" - - // TIP: You will often need to import the package that this test file lives - // in. Since it is in the "test" context, it must import the package to use - // any normal context constants, variables, or functions. tfnetworkfirewall "github.com/hashicorp/terraform-provider-aws/internal/service/networkfirewall" + "github.com/hashicorp/terraform-provider-aws/names" ) -// TIP: File Structure. The basic outline for all test files should be as -// follows. Improve this resource's maintainability by following this -// outline. -// -// 1. Package declaration (add "_test" since this is a test file) -// 2. Imports -// 3. Unit tests -// 4. Basic test -// 5. Disappears test -// 6. All the other tests -// 7. Helper functions (exists, destroy, check, etc.) -// 8. Functions that return Terraform configurations - -// TIP: ==== UNIT TESTS ==== -// This is an example of a unit test. Its name is not prefixed with -// "TestAcc" like an acceptance test. -// -// Unlike acceptance tests, unit tests do not access AWS and are focused on a -// function (or method). Because of this, they are quick and cheap to run. -// -// In designing a resource's implementation, isolate complex bits from AWS bits -// so that they can be tested through a unit test. We encourage more unit tests -// in the provider. -// -// Cut and dry functions using well-used patterns, like typical flatteners and -// expanders, don't need unit testing. However, if they are complex or -// intricate, they should be unit tested. -// func TestTLSInspectionConfigurationExampleUnitTest(t *testing.T) { -// t.Parallel() - -// testCases := []struct { -// TestName string -// Input string -// Expected string -// Error bool -// }{ -// { -// TestName: "empty", -// Input: "", -// Expected: "", -// Error: true, -// }, -// { -// TestName: "descriptive name", -// Input: "some input", -// Expected: "some output", -// Error: false, -// }, -// { -// TestName: "another descriptive name", -// Input: "more input", -// Expected: "more output", -// Error: false, -// }, -// } - -// for _, testCase := range testCases { -// testCase := testCase -// t.Run(testCase.TestName, func(t *testing.T) { -// t.Parallel() -// got, err := tfnetworkfirewall.FunctionFromResource(testCase.Input) - -// if err != nil && !testCase.Error { -// t.Errorf("got error (%s), expected no error", err) -// } - -// if err == nil && testCase.Error { -// t.Errorf("got (%s) and no error, expected error", got) -// } - -// if got != testCase.Expected { -// t.Errorf("got %s, expected %s", got, testCase.Expected) -// } -// }) -// } -// } - -// TIP: ==== ACCEPTANCE TESTS ==== -// This is an example of a basic acceptance test. This should test as much of -// standard functionality of the resource as possible, and test importing, if -// applicable. We prefix its name with "TestAcc", the service, and the -// resource name. -// -// Acceptance test access AWS and cost money to run. - // NOTE: acceptance tests require environment variable ACM_CERTIFICATE_ARN // to be set and the ACM certificate to be validated during testing. diff --git a/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown new file mode 100644 index 00000000000..1d8cb334e8c --- /dev/null +++ b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown @@ -0,0 +1,366 @@ +--- +subcategory: "Network Firewall" +layout: "aws" +page_title: "AWS: aws_networkfirewall_tls_inspection_configuration" +description: |- + Terraform resource for managing an AWS Network Firewall TLS Inspection Configuration. +--- +# Resource: aws_networkfirewall_tls_inspection_configuration + +Terraform resource for managing an AWS Network Firewall TLS Inspection Configuration. + +## Example Usage + +~> **NOTE:** You must configure either inbound inspection, outbound inspection, or both. + +### Basic inbound/ingress inspection + +``` +resource "aws_networkfirewall_tls_inspection_configuration" "example" { + name = "example" + description = "example" + encryption_configuration { + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" + } + tls_inspection_configuration { + server_certificate_configurations { + server_certificates { + resource_arn = aws_acm_certificate.example_1.arn + } + scopes { + protocols = [6] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +``` + +### Basic outbound/engress inspection + +``` +resource "aws_networkfirewall_tls_inspection_configuration" "example" { + name = "example" + description = "example" + encryption_configuration { + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = aws_acm_certificate.example_1.arn + check_certificate_revocation_status { + revoked_status_action = "REJECT" + unknown_status_action = "PASS" + } + scopes { + protocols = [6] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +``` + +### Inbound with encryption configuration + +``` +resource "aws_kms_key" "example" { + description = "example" + deletion_window_in_days = 7 +} + +resource "aws_networkfirewall_tls_inspection_configuration" "example" { + name = "example" + description = "example" + encryption_configuration { + key_id = aws_kms_key.example.arn + type = "CUSTOMER_KMS" + } + tls_inspection_configuration { + server_certificate_configurations { + server_certificates { + resource_arn = aws_acm_certificate.example_1.arn + } + scopes { + protocols = [6] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +``` + +### Outbound with encryption configuration + +``` +resource "aws_kms_key" "example" { + description = "example" + deletion_window_in_days = 7 +} + +resource "aws_networkfirewall_tls_inspection_configuration" "example" { + name = "example" + description = "example" + encryption_configuration { + key_id = aws_kms_key.example.arn + type = "CUSTOMER_KMS" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = aws_acm_certificate.example_1.arn + check_certificate_revocation_status { + revoked_status_action = "REJECT" + unknown_status_action = "PASS" + } + scopes { + protocols = [6] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +``` + +### Combined inbound and outbound + +```terraform +resource "aws_networkfirewall_tls_inspection_configuration" "example" { + name = "example" + description = "example" + encryption_configuration { + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = aws_acm_certificate.example_1.arn + check_certificate_revocation_status { + revoked_status_action = "REJECT" + unknown_status_action = "PASS" + } + server_certificates { + resource_arn = aws_acm_certificate.example_2.arn + } + scopes { + protocols = [6] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `name` - (Required, Forces new resource) Descriptive name of the TLS inspection configuration. + +* `tls_inspection_configuration` - (Required) TLS inspection configuration block. Detailed below. + +The following arguments are optional: + +* `description` - (Optional) Description of the TLS inspection configuration. + +* `encryption_configuration` - (Optional) Encryption configuration block. Detailed below. + +### Encryption Configuration + +* `key_id` - (Optional) ID of the Amazon Web Services Key Management Service (KMS) customer managed key. You can use any of the key identifiers that KMS supports, unless you're using a key that's managed by another account. If you're using a key managed by another account, then specify the key ARN. +* `type` - (Optional) Type of KMS key to use for encryption of your Network Firewall resources. Valid values: `AWS_OWNED_KMS_KEY`, `CUSTOMER_KMS`. + +### TLS Inspection Configuration + +* `server_certificate_configurations` - (Required) Server certificate configurations that are associated with the TLS configuration. Detailed below. + +### Server Certificate Configurations + +The `server_certificate_configurations` block supports the following arguments: + +* `certificate_authority_arn` - (Optional) ARN of the imported certificate authority (CA) certificate within Certificate Manager (ACM) to use for outbound SSL/TLS inspection. See [Using SSL/TLS certificates with TLS inspection configurations](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html) for limitations on CA certificates. + +* `check_certificate_revocation_status` (Optional) - Check Certificate Revocation Status block. Detailed below. + +* `scopes` (Required) - Scopes block. Detailed below. + +* `server_certificates` - (Optional) Server certificates to use for inbound SSL/TLS inspection. See [Using SSL/TLS certificates with TLS inspection configurations](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html). + +### Check Certificate Revocation Status + +The `check_certificate_revocation_status` block supports the following arguments: + +~> **NOTE To check the certificate revocation status, you must also specify a `certificate_authority_arn` in `server_certificate_configurations`. + +`revoked_status_action` - (Optional) how Network Firewall processes traffic when it determines that the certificate presented by the server in the SSL/TLS connection has a revoked status. See [Checking certificate revocation status](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html#tls-inspection-check-certificate-revocation-status) for details. Valid values: `PASS`, `DROP`, `REJECT`. + +`unknown_status_action` - (Optional) How Network Firewall processes traffic when it determines that the certificate presented by the server in the SSL/TLS connection has an unknown status, or a status that cannot be determined for any other reason, including when the service is unable to connect to the OCSP and CRL endpoints for the certificate. See [Checking certificate revocation status](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html#tls-inspection-check-certificate-revocation-status) for details. Valid values: `PASS`, `DROP`, `REJECT`. + +### Scopes + +The `scopes` block supports the following arguments: + +* `destinations` - (Optional) Set of configuration blocks describing the destination IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any destination address. See [Destination](#destination) below for details. + +* `destination_ports` - (Optional) Set of configuration blocks describing the destination ports to inspect for. If not specified, this matches with any destination port. See [Destination Port](#destination-port) below for details. + +* `protocols` - (Optional) Set of protocols to inspect for, specified using the protocol's assigned internet protocol number (IANA). Network Firewall currently supports TCP only. Valid values: `6` + +* `sources` - (Optional) Set of configuration blocks describing the source IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any source address. See [Source](#source) below for details. + +* `source_ports` - (Optional) Set of configuration blocks describing the source ports to inspect for. If not specified, this matches with any source port. See [Source Port](#source-port) below for details. + +### Destination + +The `destination` block supports the following argument: + +* `address_definition` - (Required) An IP address or a block of IP addresses in CIDR notation. AWS Network Firewall supports all address ranges for IPv4. + +### Destination Port + +The `destination_ports` block supports the following arguments: + +* `from_ports` - (Required) The lower limit of the port range. This must be less than or equal to the `to_port`. + +* `to_ports` - (Optional) The upper limit of the port range. This must be greater than or equal to the `from_port`. + +### Source + +The `source` block supports the following argument: + +* `address_definition` - (Required) An IP address or a block of IP addresses in CIDR notation. AWS Network Firewall supports all address ranges for IPv4. + +### Source Ports + +The `source_ports` block supports the following arguments: + +* `from_port` - (Required) The lower limit of the port range. This must be less than or equal to the `to_port`. + +* `to_port` - (Optional) The upper limit of the port range. This must be greater than or equal to the `from_port`. + +### Server Certificates + +The `server_certificates` block supports the following arguments: + +* `resource_arn` - (Optional) ARN of the Certificate Manager SSL/TLS server certificate that's used for inbound SSL/TLS inspection. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `arn` - ARN of the TLS Inspection Configuration. +* `certificate_authority` - Certificate Manager certificate block. See [Certificate Authority](#certificate-authority) below for details. +* `certificates` - List of certificate blocks describing certificates associated with the TLS inspection configuration. See [Certificates](#certificates) below for details. +* `last_modified_time` - Last time that the TLS inspection configuration was changed, in UTC [RFC3339](https://tools.ietf.org/html/rfc3339#section-5.8) format(for example, YYYY-MM-DDTHH:MM:SSZ). +* `number_of_associations` - Number of firewall policies that use this TLS inspection configuration. +* `status` - Current status of a TLS inspection configuration. +* `update_token` - String token used when updating the rule group. + +### Certificate Authority + +The `certificate_authority` block exports the following attributes: + +* `certificate_arn` - ARN of the certificate. +* `certificate_serial` - Serial number of the certificate. +* `status` - Status of the certificate. +* `status_message` - Details about the certificate status, including information about certificate errors. + +### Certificates + +The `certificates` block exports the following attributes: + +* `certificate_arn` - ARN of the certificate. +* `certificate_serial` - Serial number of the certificate. +* `status` - Status of the certificate. +* `status_message` - Details about the certificate status, including information about certificate errors. + +## Timeouts + +[Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): + +* `create` - (Default `60m`) +* `update` - (Default `180m`) +* `delete` - (Default `90m`) + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import Network Firewall TLS Inspection Configuration using the `arn`. For example: + +```terraform +import { + to = aws_networkfirewall_tls_inspection_configuration.example + id = "arn:aws:network-firewall::::tls-configuration/example" +} +``` + +Using `terraform import`, import Network Firewall TLS Inspection Configuration using the `arn`. For example: + +```console +% terraform import aws_networkfirewall_tls_inspection_configuration.example arn:aws:network-firewall::::tls-configuration/example +``` From 743acadc6f2a9f3e3e8bcf9c34a4e87a66944c05 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:18:13 -0500 Subject: [PATCH 19/68] Add validators to schema --- .../tls_inspection_configuration.go | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 78565c32362..12db03b579f 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -8,12 +8,13 @@ import ( "errors" "time" + "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go/service/networkfirewall" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - - // "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" @@ -71,6 +72,12 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res "arn": framework.ARNAttributeComputedOnly(), "description": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 512), + stringvalidator.RegexMatches( + regexache.MustCompile(`^.*$`), "Must provide a valid ARN", + ), + }, }, "certificate_authority": schema.ListAttribute{ Computed: true, @@ -102,6 +109,10 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), }, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 128), + stringvalidator.RegexMatches(regexache.MustCompile(`^[a-zA-Z0-9-]+$`), "Must contain only alphanumeric characters and dash '-'"), + }, }, "last_modified_time": schema.StringAttribute{ Computed: true, @@ -143,13 +154,23 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, "tls_inspection_configuration": schema.ListNestedBlock{ + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, NestedObject: schema.NestedBlockObject{ Blocks: map[string]schema.Block{ "server_certificate_configurations": schema.ListNestedBlock{ + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "certificate_authority_arn": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 256), + stringvalidator.RegexMatches(regexache.MustCompile(`^arn:aws.*`), "Must provide a valid ARN"), + }, }, }, Blocks: map[string]schema.Block{ @@ -170,12 +191,18 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res Attributes: map[string]schema.Attribute{ "resource_arn": schema.StringAttribute{ Optional: true, - // TODO: Add string validation with regex + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 256), + stringvalidator.RegexMatches(regexache.MustCompile(`^arn:aws.*`), "Must provide a valid ARN"), + }, }, }, }, }, "scopes": schema.ListNestedBlock{ + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "protocols": schema.ListAttribute{ @@ -189,9 +216,15 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res Attributes: map[string]schema.Attribute{ "from_port": schema.Int64Attribute{ Required: true, + Validators: []validator.Int64{ + int64validator.Between(0, 65535), + }, }, "to_port": schema.Int64Attribute{ Required: true, + Validators: []validator.Int64{ + int64validator.Between(0, 65535), + }, }, }, }, @@ -201,6 +234,10 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res Attributes: map[string]schema.Attribute{ "address_definition": schema.StringAttribute{ Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 255), + stringvalidator.RegexMatches(regexache.MustCompile(`^([a-fA-F\d:\.]+($|/\d{1,3}))$`), "Must contain IP address or a block of IP addresses in Classless Inter-Domain Routing (CIDR) notation"), + }, }, }, }, @@ -210,9 +247,15 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res Attributes: map[string]schema.Attribute{ "from_port": schema.Int64Attribute{ Required: true, + Validators: []validator.Int64{ + int64validator.Between(0, 65535), + }, }, "to_port": schema.Int64Attribute{ Required: true, + Validators: []validator.Int64{ + int64validator.Between(0, 65535), + }, }, }, }, @@ -222,6 +265,10 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res Attributes: map[string]schema.Attribute{ "address_definition": schema.StringAttribute{ Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 255), + stringvalidator.RegexMatches(regexache.MustCompile(`^([a-fA-F\d:\.]+($|/\d{1,3}))$`), "Must contain IP address or a block of IP addresses in Classless Inter-Domain Routing (CIDR) notation"), + }, }, }, }, From 144ed302798e6357b41dfce0333a2714f97d3645 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:22:00 -0500 Subject: [PATCH 20/68] Fix hash links in docs --- ...tworkfirewall_tls_inspection_configuration.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown index 1d8cb334e8c..94d46f32afe 100644 --- a/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown +++ b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown @@ -268,13 +268,13 @@ The `scopes` block supports the following arguments: * `destinations` - (Optional) Set of configuration blocks describing the destination IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any destination address. See [Destination](#destination) below for details. -* `destination_ports` - (Optional) Set of configuration blocks describing the destination ports to inspect for. If not specified, this matches with any destination port. See [Destination Port](#destination-port) below for details. +* `destination_ports` - (Optional) Set of configuration blocks describing the destination ports to inspect for. If not specified, this matches with any destination port. See [Destination Ports](#destination-ports) below for details. * `protocols` - (Optional) Set of protocols to inspect for, specified using the protocol's assigned internet protocol number (IANA). Network Firewall currently supports TCP only. Valid values: `6` * `sources` - (Optional) Set of configuration blocks describing the source IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any source address. See [Source](#source) below for details. -* `source_ports` - (Optional) Set of configuration blocks describing the source ports to inspect for. If not specified, this matches with any source port. See [Source Port](#source-port) below for details. +* `source_ports` - (Optional) Set of configuration blocks describing the source ports to inspect for. If not specified, this matches with any source port. See [Source Ports](#source-ports) below for details. ### Destination @@ -282,7 +282,7 @@ The `destination` block supports the following argument: * `address_definition` - (Required) An IP address or a block of IP addresses in CIDR notation. AWS Network Firewall supports all address ranges for IPv4. -### Destination Port +### Destination Ports The `destination_ports` block supports the following arguments: From 860742e61d3dfee20f996240f8376d653b8817a6 Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:00:55 -0500 Subject: [PATCH 21/68] Cleanup, run linters --- .../tls_inspection_configuration.go | 73 ++++++++----------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 12db03b579f..af303f305c2 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -41,11 +41,6 @@ import ( func newResourceTLSInspectionConfiguration(_ context.Context) (resource.ResourceWithConfigure, error) { r := &resourceTLSInspectionConfiguration{} - // TIP: ==== CONFIGURABLE TIMEOUTS ==== - // Users can configure timeout lengths but you need to use the times they - // provide. Access the timeout they configure (or the defaults) using, - // e.g., r.CreateTimeout(ctx, plan.Timeouts) (see below). The times here are - // the defaults if they don't configure timeouts. r.SetDefaultCreateTimeout(30 * time.Minute) r.SetDefaultUpdateTimeout(30 * time.Minute) r.SetDefaultDeleteTimeout(30 * time.Minute) @@ -338,13 +333,6 @@ func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req res ) return } - // if out == nil || out.TLSInspectionConfigurationResponse == nil { - // resp.Diagnostics.AddError( - // create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), nil), - // errors.New("empty output").Error(), - // ) - // return - // } plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) // Set ID to ARN since ID value is not used for describe, update, delete or list API calls @@ -421,11 +409,8 @@ func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resou resp.Diagnostics.Append(d...) state.CertificateAuthority = certificateAuthority - resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfigurationResponse.Certificates, &state.Certificates)...) - resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfiguration, &state.TLSInspectionConfiguration)...) - tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) resp.Diagnostics.Append(d...) state.TLSInspectionConfiguration = tlsInspectionConfiguration @@ -834,29 +819,29 @@ func flattenServerCertificates(ctx context.Context, serverCertificateList []*net return listVal, diags } -func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} +// func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { +// var diags diag.Diagnostics +// elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} - if len(certificateList) == 0 { - return types.ListNull(elemType), diags - } +// if len(certificateList) == 0 { +// return types.ListNull(elemType), diags +// } - elems := []attr.Value{} - for _, certificate := range certificateList { - if certificate == nil { - continue - } - flattenedCertificate, d := flattenTLSCertificate(ctx, certificate) - diags.Append(d...) - elems = append(elems, flattenedCertificate) - } +// elems := []attr.Value{} +// for _, certificate := range certificateList { +// if certificate == nil { +// continue +// } +// flattenedCertificate, d := flattenTLSCertificate(ctx, certificate) +// diags.Append(d...) +// elems = append(elems, flattenedCertificate) +// } - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) +// listVal, d := types.ListValue(elemType, elems) +// diags.Append(d...) - return listVal, diags -} +// return listVal, diags +// } func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { var diags diag.Diagnostics @@ -900,7 +885,7 @@ func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertific diags.Append(d...) destinations, d := flattenSourceDestinations(ctx, scope.Destinations) diags.Append(d...) - protocols, d := flattenProtocols(ctx, scope.Protocols) + protocols, d := flattenProtocols(scope.Protocols) diags.Append(d...) sourcePorts, d := flattenPortRange(ctx, scope.SourcePorts) diags.Append(d...) @@ -927,7 +912,7 @@ func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertific } -func flattenProtocols(ctx context.Context, list []*int64) (types.List, diag.Diagnostics) { +func flattenProtocols(list []*int64) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.Int64Type @@ -1082,7 +1067,7 @@ func expandServerCertificateConfigurations(ctx context.Context, tfList []serverC if !item.CheckCertificateRevocationsStatus.IsNull() { var certificateRevocationStatus []checkCertificateRevocationStatusData diags.Append(item.CheckCertificateRevocationsStatus.ElementsAs(ctx, &certificateRevocationStatus, false)...) - conf.CheckCertificateRevocationStatus = expandCheckCertificateRevocationStatus(ctx, certificateRevocationStatus) + conf.CheckCertificateRevocationStatus = expandCheckCertificateRevocationStatus(certificateRevocationStatus) } if !item.Scope.IsNull() { var scopesList []scopeData @@ -1102,7 +1087,7 @@ func expandServerCertificateConfigurations(ctx context.Context, tfList []serverC return apiObject } -func expandCheckCertificateRevocationStatus(ctx context.Context, tfList []checkCertificateRevocationStatusData) *networkfirewall.CheckCertificateRevocationStatusActions { +func expandCheckCertificateRevocationStatus(tfList []checkCertificateRevocationStatusData) *networkfirewall.CheckCertificateRevocationStatusActions { if len(tfList) == 0 { return nil } @@ -1142,22 +1127,22 @@ func expandScopes(ctx context.Context, tfList []scopeData) []*networkfirewall.Se if !tfObj.DestinationPorts.IsNull() { var destinationPorts []portRangeData diags.Append(tfObj.DestinationPorts.ElementsAs(ctx, &destinationPorts, false)...) - item.DestinationPorts = expandPortRange(ctx, destinationPorts) + item.DestinationPorts = expandPortRange(destinationPorts) } if !tfObj.Destinations.IsNull() { var destinations []sourceDestinationData diags.Append(tfObj.Destinations.ElementsAs(ctx, &destinations, false)...) - item.Destinations = expandSourceDestinations(ctx, destinations) + item.Destinations = expandSourceDestinations(destinations) } if !tfObj.SourcePorts.IsNull() { var sourcePorts []portRangeData diags.Append(tfObj.SourcePorts.ElementsAs(ctx, &sourcePorts, false)...) - item.SourcePorts = expandPortRange(ctx, sourcePorts) + item.SourcePorts = expandPortRange(sourcePorts) } if !tfObj.Sources.IsNull() { var sources []sourceDestinationData diags.Append(tfObj.Sources.ElementsAs(ctx, &sources, false)...) - item.Sources = expandSourceDestinations(ctx, sources) + item.Sources = expandSourceDestinations(sources) } apiObject = append(apiObject, item) } @@ -1165,7 +1150,7 @@ func expandScopes(ctx context.Context, tfList []scopeData) []*networkfirewall.Se return apiObject } -func expandPortRange(ctx context.Context, tfList []portRangeData) []*networkfirewall.PortRange { +func expandPortRange(tfList []portRangeData) []*networkfirewall.PortRange { var apiObject []*networkfirewall.PortRange for _, tfObj := range tfList { @@ -1179,7 +1164,7 @@ func expandPortRange(ctx context.Context, tfList []portRangeData) []*networkfire return apiObject } -func expandSourceDestinations(ctx context.Context, tfList []sourceDestinationData) []*networkfirewall.Address { +func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall.Address { var apiObject []*networkfirewall.Address for _, tfObj := range tfList { From 496564278e5287d0a08f24f5b47eb44d0f73f0dc Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Tue, 20 Feb 2024 09:25:22 -0500 Subject: [PATCH 22/68] Rerun golangci-lint --- .../tls_inspection_configuration.go | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index af303f305c2..407328c6d59 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -449,7 +449,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res return } in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(ctx, tfList) - } if !plan.EncryptionConfiguration.IsNull() { @@ -730,7 +729,6 @@ func flattenTLSInspectionConfiguration(ctx context.Context, tlsInspectionConfigu diags.Append(d...) return listVal, diags - } func flattenServerCertificateConfigurations(ctx context.Context, serverCertificateConfigurations []*networkfirewall.ServerCertificateConfiguration) (types.List, diag.Diagnostics) { @@ -819,30 +817,6 @@ func flattenServerCertificates(ctx context.Context, serverCertificateList []*net return listVal, diags } -// func flattenCertificates(ctx context.Context, certificateList []*networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { -// var diags diag.Diagnostics -// elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} - -// if len(certificateList) == 0 { -// return types.ListNull(elemType), diags -// } - -// elems := []attr.Value{} -// for _, certificate := range certificateList { -// if certificate == nil { -// continue -// } -// flattenedCertificate, d := flattenTLSCertificate(ctx, certificate) -// diags.Append(d...) -// elems = append(elems, flattenedCertificate) -// } - -// listVal, d := types.ListValue(elemType, elems) -// diags.Append(d...) - -// return listVal, diags -// } - func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { var diags diag.Diagnostics elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} @@ -864,7 +838,6 @@ func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.Tls diags.Append(d...) return listVal, diags - } func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertificateScope) (types.List, diag.Diagnostics) { @@ -909,7 +882,6 @@ func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertific diags.Append(d...) return listVal, diags - } func flattenProtocols(list []*int64) (types.List, diag.Diagnostics) { @@ -1015,9 +987,7 @@ func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfigurat diags.Append(d...) return listVal, diags - } - // TODO: add note explaining why not using existing expandEncryptionConfiguration() func expandTLSEncryptionConfiguration(tfList []encryptionConfigurationData) *networkfirewall.EncryptionConfiguration { if len(tfList) == 0 { From acf4d32c6e98f528d1b4912b49f4b5fd120d933d Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Tue, 20 Feb 2024 09:38:11 -0500 Subject: [PATCH 23/68] Add changelog --- .changelog/35168.txt | 3 +++ .../service/networkfirewall/tls_inspection_configuration.go | 1 + 2 files changed, 4 insertions(+) create mode 100644 .changelog/35168.txt diff --git a/.changelog/35168.txt b/.changelog/35168.txt new file mode 100644 index 00000000000..4fbe7f14ec8 --- /dev/null +++ b/.changelog/35168.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_networkfirewall_tls_inspection_configuration +``` \ No newline at end of file diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 407328c6d59..5cfb2418be1 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -988,6 +988,7 @@ func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfigurat return listVal, diags } + // TODO: add note explaining why not using existing expandEncryptionConfiguration() func expandTLSEncryptionConfiguration(tfList []encryptionConfigurationData) *networkfirewall.EncryptionConfiguration { if len(tfList) == 0 { From d55771790897cf3f78beb765191a1ebbf62220ea Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:07:22 -0500 Subject: [PATCH 24/68] Re-run linters --- internal/service/networkfirewall/tls_inspection_configuration.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 5cfb2418be1..d97ff7cad3d 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -431,7 +431,6 @@ func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req res if !plan.Description.Equal(state.Description) || !plan.TLSInspectionConfiguration.Equal(state.TLSInspectionConfiguration) || !plan.EncryptionConfiguration.Equal(state.EncryptionConfiguration) { - in := &networkfirewall.UpdateTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(plan.ARN.ValueString()), TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), From e45196336de780cf6c30209f8653e22d0dae122b Mon Sep 17 00:00:00 2001 From: Dave DeRicco <30156588+ddericco@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:28:50 -0500 Subject: [PATCH 25/68] Add additional acceptance tests, cleanup --- .../tls_inspection_configuration_test.go | 185 +++++++++++------- 1 file changed, 109 insertions(+), 76 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index ecb8ebd14f4..ecc982fc484 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -46,11 +46,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic resourceName := "aws_networkfirewall_tls_inspection_configuration.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) - testAccPreCheck(ctx, t) - }, + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), @@ -140,24 +136,15 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) } rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_tls_inspection_configuration.test" - commonName := "example.com" - caKey := acctest.TLSRSAPrivateKeyPEM(t, 4096) - caCertificate := acctest.TLSRSAX509SelfSignedCACertificatePEM(t, caKey) - key := acctest.TLSRSAPrivateKeyPEM(t, 4096) - certificate := acctest.TLSRSAX509LocallySignedCertificatePEM(t, caKey, caCertificate, key, commonName) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) - testAccPreCheck(ctx, t) - }, + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_egressBasic(rName, certificate, key, caCertificate, ca), + Config: testAccTLSInspectionConfigurationConfig_egressBasic(rName, ca), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), resource.TestCheckResourceAttr(resourceName, "name", rName), @@ -188,7 +175,62 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, + }, + }, + }) +} + +func TestAccNetworkFirewallTLSInspectionConfiguration_egressWithEncryptionConfiguration(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput + ca := os.Getenv("ACM_CA_CERTIFICATE_ARN") + if ca == "" { + t.Skipf("Environment variable %s is not set, skipping test", ca) + } + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + keyName := "aws_kms_key.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_egressWithEncryptionConfiguration(rName, ca), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, "arn"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", ca), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), + acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, }, }, }) @@ -209,11 +251,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) resourceName := "aws_networkfirewall_tls_inspection_configuration.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) - testAccPreCheck(ctx, t) - }, + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), @@ -250,7 +288,6 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, }, }, }) @@ -272,11 +309,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfi keyName := "aws_kms_key.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - // acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) - testAccPreCheck(ctx, t) - }, + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), @@ -303,7 +336,6 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfi resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), - // resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, @@ -311,7 +343,6 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfi ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - // ImportStateVerifyIgnore: []string{"apply_immediately", "user"}, }, }, }) @@ -322,32 +353,25 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_disappears(t *testing.T) { if testing.Short() { t.Skip("skipping long-running test in short mode") } + certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") + if certificateArn == "" { + t.Skipf("Environment variable %s is not set, skipping test", certificateArn) + } var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - domainName := acctest.ACMCertificateDomainFromEnv(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_tls_inspection_configuration.test" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - acctest.PreCheck(ctx, t) - acctest.PreCheckPartitionHasService(t, names.NetworkFirewall) - testAccPreCheck(ctx, t) - }, + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_ingressBasic(rName, domainName), + Config: testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateArn), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - // TIP: The Plugin-Framework disappears helper is similar to the Plugin-SDK version, - // but expects a new resource factory function as the third argument. To expose this - // private function to the testing package, you may need to add a line like the following - // to exports_test.go: - // - // var ResourceTLSInspectionConfiguration = newResourceTLSInspectionConfiguration acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfnetworkfirewall.ResourceTLSInspectionConfiguration, resourceName), ), ExpectNonEmptyPlan: true, @@ -409,30 +433,6 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name stri } } -// func testAccPreCheck(ctx context.Context, t *testing.T) { -// conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) - -// input := &networkfirewall.ListTLSInspectionConfigurationsInput{} -// _, err := conn.ListTLSInspectionConfigurationsWithContext(ctx, input) - -// if acctest.PreCheckSkipError(err) { -// t.Skipf("skipping acceptance testing: %s", err) -// } -// if err != nil { -// t.Fatalf("unexpected PreCheck error: %s", err) -// } -// } - -// func testAccCheckTLSInspectionConfigurationNotRecreated(before, after *networkfirewall.DescribeTLSInspectionConfigurationOutput) resource.TestCheckFunc { -// return func(s *terraform.State) error { -// if before, after := aws.ToString(before.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId), aws.ToString(after.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId); before != after { -// return create.Error(names.NetworkFirewall, create.ErrActionCheckingNotRecreated, tfnetworkfirewall.ResNameTLSInspectionConfiguration, aws.ToString(before.TLSInspectionConfigurationId), errors.New("recreated")) -// } - -// return nil -// } -// } - func testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateARN, ca string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { @@ -600,14 +600,8 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { `, rName, certificateARN)) } -func testAccTLSInspectionConfigurationConfig_egressBasic(rName, certificate, privateKey, chain, ca string) string { +func testAccTLSInspectionConfigurationConfig_egressBasic(rName, ca string) string { return fmt.Sprintf(` -resource "aws_acm_certificate" "test" { - certificate_body = "%[2]s" - private_key = "%[3]s" - certificate_chain = "%[4]s" -} - resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" @@ -617,7 +611,46 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } tls_inspection_configuration { server_certificate_configurations { - certificate_authority_arn = %[5]q + certificate_authority_arn = %[2]q + check_certificate_revocation_status { + revoked_status_action = "REJECT" + unknown_status_action = "PASS" + } + scopes { + protocols = [6] + destination_ports { + from_port = 443 + to_port = 443 + } + destinations { + address_definition = "0.0.0.0/0" + } + source_ports { + from_port = 0 + to_port = 65535 + } + sources { + address_definition = "0.0.0.0/0" + } + } + } + } +} +`, rName, ca) +} + +func testAccTLSInspectionConfigurationConfig_egressWithEncryptionConfiguration(rName, ca string) string { + return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName), fmt.Sprintf(` +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + description = "test" + encryption_configuration { + key_id = aws_kms_key.test.arn + type = "CUSTOMER_KMS" + } + tls_inspection_configuration { + server_certificate_configurations { + certificate_authority_arn = %[2]q check_certificate_revocation_status { revoked_status_action = "REJECT" unknown_status_action = "PASS" @@ -642,5 +675,5 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } } -`, rName, acctest.TLSPEMEscapeNewlines(certificate), acctest.TLSPEMEscapeNewlines(privateKey), acctest.TLSPEMEscapeNewlines(chain), ca) +`, rName, ca)) } From cb2da57f4773c85051a927f7d42cad1b9c198c28 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 18 Jun 2024 11:26:14 -0400 Subject: [PATCH 26/68] ec2: Skip 'UnsupportedOperation: The functionality you requested is not available in this region' errors. --- internal/sweep/awsv2/skip.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/sweep/awsv2/skip.go b/internal/sweep/awsv2/skip.go index 44269e7339b..579c7eb229b 100644 --- a/internal/sweep/awsv2/skip.go +++ b/internal/sweep/awsv2/skip.go @@ -53,6 +53,10 @@ func SkipSweepError(err error) bool { if tfawserr.ErrMessageContains(err, "InvalidInputException", "Domain-related APIs are only available in the us-east-1 Region") { return true } + // Example (ec2): UnsupportedOperation: The functionality you requested is not available in this region + if tfawserr.ErrMessageContains(err, "UnsupportedOperation", "The functionality you requested is not available in this region") { + return true + } return false } From cfaeca4fd65401f1cbf9df3e93b2a73486263315 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 18 Jun 2024 16:58:09 -0400 Subject: [PATCH 27/68] r/aws_networkfirewall_tls_inspection_configuration: Use AutoFlEx. --- internal/framework/types/setof.go | 1 + .../service/networkfirewall/exports_test.go | 5 +- .../networkfirewall/service_package_gen.go | 5 +- .../tls_inspection_configuration.go | 1213 +++++------------ .../tls_inspection_configuration_test.go | 237 ++-- ...tls_inspection_configuration.html.markdown | 82 +- 6 files changed, 466 insertions(+), 1077 deletions(-) diff --git a/internal/framework/types/setof.go b/internal/framework/types/setof.go index 357f1f63f8b..8588aab42e5 100644 --- a/internal/framework/types/setof.go +++ b/internal/framework/types/setof.go @@ -25,6 +25,7 @@ type setTypeOf[T attr.Value] struct { } var ( + SetOfInt64Type = setTypeOf[basetypes.Int64Value]{basetypes.SetType{ElemType: basetypes.Int64Type{}}} SetOfStringType = setTypeOf[basetypes.StringValue]{basetypes.SetType{ElemType: basetypes.StringType{}}} ) diff --git a/internal/service/networkfirewall/exports_test.go b/internal/service/networkfirewall/exports_test.go index f488ce5682d..91246b3d0d8 100644 --- a/internal/service/networkfirewall/exports_test.go +++ b/internal/service/networkfirewall/exports_test.go @@ -3,6 +3,9 @@ package networkfirewall +// Exports for use in tests only. var ( - ResourceTLSInspectionConfiguration = newResourceTLSInspectionConfiguration + ResourceTLSInspectionConfiguration = newTLSInspectionConfigurationResource + + FindTLSInspectionConfigurationByARN = findTLSInspectionConfigurationByARN ) diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 980aa8d8140..fb8f458a59c 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -24,8 +24,11 @@ func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.Serv func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { return []*types.ServicePackageFrameworkResource{ { - Factory: newResourceTLSInspectionConfiguration, + Factory: newTLSInspectionConfigurationResource, Name: "TLS Inspection Configuration", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: names.AttrARN, + }, }, } } diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index d97ff7cad3d..a92f1bfe14c 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -5,19 +5,18 @@ package networkfirewall import ( "context" - "errors" + "fmt" "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/networkfirewall" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" @@ -27,19 +26,20 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "github.com/hashicorp/terraform-provider-aws/internal/create" "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag" "github.com/hashicorp/terraform-provider-aws/internal/framework" - "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwflex "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) -// Function annotations are used for resource registration to the Provider. DO NOT EDIT. // @FrameworkResource(name="TLS Inspection Configuration") -func newResourceTLSInspectionConfiguration(_ context.Context) (resource.ResourceWithConfigure, error) { - r := &resourceTLSInspectionConfiguration{} +// @Tags(identifierAttribute="arn") +func newTLSInspectionConfigurationResource(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &tlsInspectionConfigurationResource{} r.SetDefaultCreateTimeout(30 * time.Minute) r.SetDefaultUpdateTimeout(30 * time.Minute) @@ -48,58 +48,42 @@ func newResourceTLSInspectionConfiguration(_ context.Context) (resource.Resource return r, nil } -const ( - ResNameTLSInspectionConfiguration = "TLS Inspection Configuration" -) - -type resourceTLSInspectionConfiguration struct { +type tlsInspectionConfigurationResource struct { framework.ResourceWithConfigure + framework.WithImportByID framework.WithTimeouts } -func (r *resourceTLSInspectionConfiguration) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = "aws_networkfirewall_tls_inspection_configuration" +func (*tlsInspectionConfigurationResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "aws_networkfirewall_tls_inspection_configuration" } -func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ +func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ - "arn": framework.ARNAttributeComputedOnly(), - "description": schema.StringAttribute{ - Optional: true, - Validators: []validator.String{ - stringvalidator.LengthBetween(1, 512), - stringvalidator.RegexMatches( - regexache.MustCompile(`^.*$`), "Must provide a valid ARN", - ), - }, - }, + names.AttrARN: framework.ARNAttributeComputedOnly(), "certificate_authority": schema.ListAttribute{ - Computed: true, + CustomType: fwtypes.NewListNestedObjectTypeOf[tlsCertificateDataModel](ctx), + Computed: true, ElementType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "certificate_arn": types.StringType, - "certificate_serial": types.StringType, - "status": types.StringType, - "status_message": types.StringType, - }, + AttrTypes: fwtypes.AttributeTypesMust[tlsCertificateDataModel](ctx), }, }, "certificates": schema.ListAttribute{ - CustomType: fwtypes.NewListNestedObjectTypeOf[certificatesData](ctx), + CustomType: fwtypes.NewListNestedObjectTypeOf[tlsCertificateDataModel](ctx), Computed: true, ElementType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "certificate_arn": types.StringType, - "certificate_serial": types.StringType, - "status": types.StringType, - "status_message": types.StringType, - }, + AttrTypes: fwtypes.AttributeTypesMust[tlsCertificateDataModel](ctx), }, }, - "id": framework.IDAttribute(), - // Map name to TLSInspectionConfigurationName - "name": schema.StringAttribute{ + names.AttrDescription: schema.StringAttribute{ + Optional: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 512), + }, + }, + names.AttrID: framework.IDAttribute(), + names.AttrName: schema.StringAttribute{ Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), @@ -109,104 +93,104 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res stringvalidator.RegexMatches(regexache.MustCompile(`^[a-zA-Z0-9-]+$`), "Must contain only alphanumeric characters and dash '-'"), }, }, - "last_modified_time": schema.StringAttribute{ - Computed: true, - }, "number_of_associations": schema.Int64Attribute{ Computed: true, PlanModifiers: []planmodifier.Int64{ int64planmodifier.UseStateForUnknown(), }, }, - "status": schema.StringAttribute{ - Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, + names.AttrTags: tftags.TagsAttribute(), + names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), + "tls_inspection_configuration_id": framework.IDAttribute(), "update_token": schema.StringAttribute{ Computed: true, }, }, Blocks: map[string]schema.Block{ "encryption_configuration": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[encryptionConfigurationModel](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "key_id": schema.StringAttribute{ - Optional: true, - Computed: true, - Default: stringdefault.StaticString("AWS_OWNED_KMS_KEY"), + CustomType: fwtypes.ARNType, + Optional: true, + Computed: true, }, "type": schema.StringAttribute{ Optional: true, Computed: true, - Default: stringdefault.StaticString("AWS_OWNED_KMS_KEY"), + Default: stringdefault.StaticString(networkfirewall.EncryptionTypeAwsOwnedKmsKey), Validators: []validator.String{ - stringvalidator.OneOf(networkfirewall.EncryptionTypeAwsOwnedKmsKey, networkfirewall.EncryptionTypeCustomerKms), + stringvalidator.OneOf(networkfirewall.EncryptionType_Values()...), }, }, }, }, }, + "timeouts": timeouts.Block(ctx, timeouts.Opts{ + Create: true, + Update: true, + Delete: true, + }), "tls_inspection_configuration": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[tlsInspectionConfigurationModel](ctx), Validators: []validator.List{ - listvalidator.SizeAtMost(1), + listvalidator.IsRequired(), + listvalidator.SizeBetween(1, 1), }, NestedObject: schema.NestedBlockObject{ Blocks: map[string]schema.Block{ - "server_certificate_configurations": schema.ListNestedBlock{ - Validators: []validator.List{ - listvalidator.SizeAtMost(1), - }, + "server_certificate_configuration": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[serverCertificateConfigurationModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "certificate_authority_arn": schema.StringAttribute{ - Optional: true, - Validators: []validator.String{ - stringvalidator.LengthBetween(1, 256), - stringvalidator.RegexMatches(regexache.MustCompile(`^arn:aws.*`), "Must provide a valid ARN"), - }, + CustomType: fwtypes.ARNType, + Optional: true, }, }, Blocks: map[string]schema.Block{ "check_certificate_revocation_status": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[checkCertificateRevocationStatusActionsModel](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "revoked_status_action": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + stringvalidator.OneOf(networkfirewall.RevocationCheckAction_Values()...), + }, }, "unknown_status_action": schema.StringAttribute{ Optional: true, - }, - }, - }, - }, - "server_certificates": schema.ListNestedBlock{ - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - "resource_arn": schema.StringAttribute{ - Optional: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 256), - stringvalidator.RegexMatches(regexache.MustCompile(`^arn:aws.*`), "Must provide a valid ARN"), + stringvalidator.OneOf(networkfirewall.RevocationCheckAction_Values()...), }, }, }, }, }, - "scopes": schema.ListNestedBlock{ - Validators: []validator.List{ - listvalidator.SizeAtLeast(1), - }, + "scope": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[serverCertificateScopeModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ - "protocols": schema.ListAttribute{ + "protocols": schema.SetAttribute{ + CustomType: fwtypes.SetOfInt64Type, ElementType: types.Int64Type, Required: true, + Validators: []validator.Set{ + setvalidator.ValueInt64sAre(int64validator.Between(0, 255)), + }, }, }, Blocks: map[string]schema.Block{ "destination_ports": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[portRangeModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "from_port": schema.Int64Attribute{ @@ -224,7 +208,8 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, - "destinations": schema.ListNestedBlock{ + "destination": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[addressModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "address_definition": schema.StringAttribute{ @@ -238,6 +223,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, "source_ports": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[portRangeModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "from_port": schema.Int64Attribute{ @@ -256,6 +242,7 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, "sources": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[addressModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "address_definition": schema.StringAttribute{ @@ -271,994 +258,420 @@ func (r *resourceTLSInspectionConfiguration) Schema(ctx context.Context, req res }, }, }, + "server_certificate": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[serverCertificateModel](ctx), + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "resource_arn": schema.StringAttribute{ + CustomType: fwtypes.ARNType, + Optional: true, + }, + }, + }, + }, }, }, }, }, }, }, - "timeouts": timeouts.Block(ctx, timeouts.Opts{ - Create: true, - Update: true, - Delete: true, - }), }, } } -func (r *resourceTLSInspectionConfiguration) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - conn := r.Meta().NetworkFirewallConn(ctx) - - var plan resourceTLSInspectionConfigurationData - resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) - if resp.Diagnostics.HasError() { +func (r *tlsInspectionConfigurationResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var data tlsInspectionConfigurationResourceModel + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + if response.Diagnostics.HasError() { return } - in := &networkfirewall.CreateTLSInspectionConfigurationInput{ - // NOTE: Name is mandatory - TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), - } - - if !plan.Description.IsNull() { - // NOTE: Description is optional - in.Description = aws.String(plan.Description.ValueString()) - } - - if !plan.TLSInspectionConfiguration.IsNull() { - var tfList []tlsInspectionConfigurationData - resp.Diagnostics.Append(plan.TLSInspectionConfiguration.ElementsAs(ctx, &tfList, false)...) - if resp.Diagnostics.HasError() { - return - } - - in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(ctx, tfList) - } - - if !plan.EncryptionConfiguration.IsNull() { - var tfList []encryptionConfigurationData - resp.Diagnostics.Append(plan.EncryptionConfiguration.ElementsAs(ctx, &tfList, false)...) - if resp.Diagnostics.HasError() { - return - } - - in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) - } + conn := r.Meta().NetworkFirewallConn(ctx) - out, err := conn.CreateTLSInspectionConfigurationWithContext(ctx, in) - if err != nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionCreating, ResNameTLSInspectionConfiguration, plan.Name.String(), err), - err.Error(), - ) + name := data.TLSInspectionConfigurationName.ValueString() + input := &networkfirewall.CreateTLSInspectionConfigurationInput{} + response.Diagnostics.Append(fwflex.Expand(ctx, data, input)...) + if response.Diagnostics.HasError() { return } - plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - // Set ID to ARN since ID value is not used for describe, update, delete or list API calls - plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) + outputC, err := conn.CreateTLSInspectionConfigurationWithContext(ctx, input) - createTimeout := r.CreateTimeout(ctx, plan.Timeouts) - _, err = waitTLSInspectionConfigurationCreated(ctx, conn, plan.ARN.ValueString(), createTimeout) if err != nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForCreation, ResNameTLSInspectionConfiguration, plan.Name.String(), err), - err.Error(), - ) + response.Diagnostics.AddError(fmt.Sprintf("creating NetworkFirewall TLS Inspection Configuration (%s)", name), err.Error()) + return } - // Read to get computed attributes not returned from create - readComputed, _ := findTLSInspectionConfigurationByNameAndARN(ctx, conn, plan.ARN.ValueString()) + // Set values for unknowns. + data.TLSInspectionConfigurationARN = fwflex.StringToFramework(ctx, outputC.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) + data.TLSInspectionConfigurationID = fwflex.StringToFramework(ctx, outputC.TLSInspectionConfigurationResponse.TLSInspectionConfigurationId) + data.UpdateToken = fwflex.StringToFramework(ctx, outputC.UpdateToken) + data.setID() - // Set computed attributes - plan.LastModifiedTime = flex.StringValueToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) - plan.NumberOfAssociations = flex.Int64ToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.NumberOfAssociations) - plan.Status = flex.StringToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) + outputR, err := waitTLSInspectionConfigurationCreated(ctx, conn, data.ID.ValueString(), r.CreateTimeout(ctx, data.Timeouts)) - resp.Diagnostics.Append(flex.Flatten(ctx, readComputed.TLSInspectionConfigurationResponse.Certificates, &plan.Certificates)...) - - certificateAuthority, d := flattenTLSCertificate(ctx, readComputed.TLSInspectionConfigurationResponse.CertificateAuthority) - resp.Diagnostics.Append(d...) - plan.CertificateAuthority = certificateAuthority - - resp.Diagnostics.Append(resp.State.Set(ctx, plan)...) -} - -func (r *resourceTLSInspectionConfiguration) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - conn := r.Meta().NetworkFirewallConn(ctx) + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("waiting for NetworkFirewall TLS Inspection Configuration (%s) create", data.ID.ValueString()), err.Error()) - var state resourceTLSInspectionConfigurationData - resp.Diagnostics.Append(req.State.Get(ctx, &state)...) - if resp.Diagnostics.HasError() { return } - out, err := findTLSInspectionConfigurationByID(ctx, conn, state.ID.ValueString()) - if tfresource.NotFound(err) { - resp.State.RemoveResource(ctx) - return - } - if err != nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionSetting, ResNameTLSInspectionConfiguration, state.ID.String(), err), - err.Error(), - ) + // Set values for unknowns. + response.Diagnostics.Append(flattenDescribeTLSInspectionConfigurationOutput(ctx, &data, outputR)...) + if response.Diagnostics.HasError() { return } - state.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - state.Description = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.Description) - - // Set ID to ARN since ID value is not used for Describe, Update, Delete or List calls - state.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - state.Name = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationName) - - state.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) - state.NumberOfAssociations = flex.Int64ToFramework(ctx, out.TLSInspectionConfigurationResponse.NumberOfAssociations) - state.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) - state.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) - - // Complex types - encryptionConfiguration, d := flattenTLSEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) - resp.Diagnostics.Append(d...) - state.EncryptionConfiguration = encryptionConfiguration - - certificateAuthority, d := flattenTLSCertificate(ctx, out.TLSInspectionConfigurationResponse.CertificateAuthority) - resp.Diagnostics.Append(d...) - state.CertificateAuthority = certificateAuthority - - resp.Diagnostics.Append(flex.Flatten(ctx, out.TLSInspectionConfigurationResponse.Certificates, &state.Certificates)...) - - tlsInspectionConfiguration, d := flattenTLSInspectionConfiguration(ctx, out.TLSInspectionConfiguration) - resp.Diagnostics.Append(d...) - state.TLSInspectionConfiguration = tlsInspectionConfiguration - - resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) + response.Diagnostics.Append(response.State.Set(ctx, data)...) } -func (r *resourceTLSInspectionConfiguration) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - conn := r.Meta().NetworkFirewallConn(ctx) - - var plan, state resourceTLSInspectionConfigurationData - resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) - resp.Diagnostics.Append(req.State.Get(ctx, &state)...) - if resp.Diagnostics.HasError() { +func (r *tlsInspectionConfigurationResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var data tlsInspectionConfigurationResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { return } - if !plan.Description.Equal(state.Description) || - !plan.TLSInspectionConfiguration.Equal(state.TLSInspectionConfiguration) || - !plan.EncryptionConfiguration.Equal(state.EncryptionConfiguration) { - in := &networkfirewall.UpdateTLSInspectionConfigurationInput{ - TLSInspectionConfigurationArn: aws.String(plan.ARN.ValueString()), - TLSInspectionConfigurationName: aws.String(plan.Name.ValueString()), - UpdateToken: aws.String(state.UpdateToken.ValueString()), - } - - if !plan.Description.IsNull() { - in.Description = aws.String(plan.Description.ValueString()) - } + if err := data.InitFromID(); err != nil { + response.Diagnostics.AddError("parsing resource ID", err.Error()) - if !plan.TLSInspectionConfiguration.IsNull() { - var tfList []tlsInspectionConfigurationData - resp.Diagnostics.Append(plan.TLSInspectionConfiguration.ElementsAs(ctx, &tfList, false)...) - if resp.Diagnostics.HasError() { - return - } - in.TLSInspectionConfiguration = expandTLSInspectionConfiguration(ctx, tfList) - } - - if !plan.EncryptionConfiguration.IsNull() { - var tfList []encryptionConfigurationData - resp.Diagnostics.Append(plan.EncryptionConfiguration.ElementsAs(ctx, &tfList, false)...) - if resp.Diagnostics.HasError() { - return - } - in.EncryptionConfiguration = expandTLSEncryptionConfiguration(tfList) - } - - out, err := conn.UpdateTLSInspectionConfigurationWithContext(ctx, in) - if err != nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionUpdating, ResNameTLSInspectionConfiguration, plan.ID.String(), err), - err.Error(), - ) - return - } - if out == nil || out.TLSInspectionConfigurationResponse == nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionUpdating, ResNameTLSInspectionConfiguration, plan.ID.String(), nil), - errors.New("empty output").Error(), - ) - return - } - - plan.ARN = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - // Set ID to ARN since ID value is not used for describe, update, delete or list API calls - plan.ID = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationArn) - plan.LastModifiedTime = flex.StringValueToFramework(ctx, out.TLSInspectionConfigurationResponse.LastModifiedTime.Format(time.RFC3339)) - plan.UpdateToken = flex.StringToFramework(ctx, out.UpdateToken) - plan.Status = flex.StringToFramework(ctx, out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) - - encryptionConfiguration, d := flattenTLSEncryptionConfiguration(ctx, out.TLSInspectionConfigurationResponse.EncryptionConfiguration) - resp.Diagnostics.Append(d...) - plan.EncryptionConfiguration = encryptionConfiguration - - // Update does not certificates and CA, so read to backfill the missing attributes - // NOTE: number of associations should be returned according to the API docs, but isn't! - readComputed, _ := findTLSInspectionConfigurationByNameAndARN(ctx, conn, plan.ARN.ValueString()) - plan.NumberOfAssociations = flex.Int64ToFramework(ctx, readComputed.TLSInspectionConfigurationResponse.NumberOfAssociations) - - // Complex types - certificateAuthority, d := flattenTLSCertificate(ctx, readComputed.TLSInspectionConfigurationResponse.CertificateAuthority) - resp.Diagnostics.Append(d...) - plan.CertificateAuthority = certificateAuthority - - resp.Diagnostics.Append(flex.Flatten(ctx, readComputed.TLSInspectionConfigurationResponse.Certificates, &plan.Certificates)...) - } - - updateTimeout := r.UpdateTimeout(ctx, plan.Timeouts) - _, err := waitTLSInspectionConfigurationUpdated(ctx, conn, plan.ARN.ValueString(), updateTimeout) - if err != nil { - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForUpdate, ResNameTLSInspectionConfiguration, plan.ID.String(), err), - err.Error(), - ) return } - resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) -} - -func (r *resourceTLSInspectionConfiguration) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { conn := r.Meta().NetworkFirewallConn(ctx) - var state resourceTLSInspectionConfigurationData - resp.Diagnostics.Append(req.State.Get(ctx, &state)...) - if resp.Diagnostics.HasError() { - return - } + output, err := findTLSInspectionConfigurationByARN(ctx, conn, data.ID.ValueString()) - in := &networkfirewall.DeleteTLSInspectionConfigurationInput{ - TLSInspectionConfigurationArn: aws.String(state.ARN.ValueString()), - } + if tfresource.NotFound(err) { + response.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err)) + response.State.RemoveResource(ctx) - _, err := conn.DeleteTLSInspectionConfigurationWithContext(ctx, in) - if err != nil { - if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { - return - } - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionDeleting, ResNameTLSInspectionConfiguration, state.ID.String(), err), - err.Error(), - ) return } - deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts) - _, err = waitTLSInspectionConfigurationDeleted(ctx, conn, state.ARN.ValueString(), deleteTimeout) if err != nil { - if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { - return - } - resp.Diagnostics.AddError( - create.ProblemStandardMessage(names.NetworkFirewall, create.ErrActionWaitingForDeletion, ResNameTLSInspectionConfiguration, state.ID.String(), err), - err.Error(), - ) - return - } -} + response.Diagnostics.AddError(fmt.Sprintf("reading NetworkFirewall TLS Inspection Configuration (%s)", data.ID.ValueString()), err.Error()) -func (r *resourceTLSInspectionConfiguration) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) -} - -// TIP: ==== STATUS CONSTANTS ==== -// Create constants for states and statuses if the service does not -// already have suitable constants. We prefer that you use the constants -// provided in the service if available (e.g., awstypes.StatusInProgress). -const ( - statusChangePending = "Pending" - statusDeleting = "Deleting" - statusNormal = "Normal" - statusUpdated = "Updated" -) - -func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{statusChangePending}, - Target: []string{networkfirewall.ResourceStatusActive}, - Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), - Timeout: timeout, - NotFoundChecks: 20, - ContinuousTargetOccurence: 5, - } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - if out, ok := outputRaw.(*networkfirewall.TLSInspectionConfiguration); ok { - return out, err - } - - return nil, err -} - -func statusTLSInspectionConfigurationCertificates(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, arn) - if tfresource.NotFound(err) { - return nil, "", nil - } - - if err != nil { - return nil, "", err - } - - certificates := out.TLSInspectionConfigurationResponse.Certificates - certificateAuthority := out.TLSInspectionConfigurationResponse.CertificateAuthority - - // The API does not immediately return data for certificates and certificate authority even when the resource status is "ACTIVE", - // which causes unexpected diffs when reading. This sets the status to "PENDING" until either the certificates or the certificate - // authority is populated (the API will always return at least one of the two) - if aws.ToString(out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus) == networkfirewall.ResourceStatusActive && - (certificates != nil || certificateAuthority != nil) { - return out, aws.ToString(out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus), nil - } else { - return out, statusChangePending, nil - } - } -} - -func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{statusChangePending}, - Target: []string{networkfirewall.ResourceStatusActive}, - Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), - Timeout: timeout, - NotFoundChecks: 20, - ContinuousTargetOccurence: 2, + return } - outputRaw, err := stateConf.WaitForStateContext(ctx) - if out, ok := outputRaw.(*networkfirewall.TLSInspectionConfiguration); ok { - return out, err + // Set attributes for import. + response.Diagnostics.Append(flattenDescribeTLSInspectionConfigurationOutput(ctx, &data, output)...) + if response.Diagnostics.HasError() { + return } - return nil, err + response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.TLSInspectionConfiguration, error) { - stateConf := &retry.StateChangeConf{ - Pending: []string{networkfirewall.ResourceStatusDeleting, networkfirewall.ResourceStatusActive}, - Target: []string{}, - Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), - Timeout: timeout, +func (r *tlsInspectionConfigurationResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var old, new tlsInspectionConfigurationResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &old)...) + if response.Diagnostics.HasError() { + return } - - outputRaw, err := stateConf.WaitForStateContext(ctx) - if out, ok := outputRaw.(*networkfirewall.TLSInspectionConfiguration); ok { - return out, err + response.Diagnostics.Append(request.Plan.Get(ctx, &new)...) + if response.Diagnostics.HasError() { + return } - return nil, err -} + conn := r.Meta().NetworkFirewallConn(ctx) -func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { - return func() (interface{}, string, error) { - out, err := findTLSInspectionConfigurationByNameAndARN(ctx, conn, arn) - if tfresource.NotFound(err) { - return nil, "", nil + if !new.Description.Equal(old.Description) || + !new.EncryptionConfiguration.Equal(old.EncryptionConfiguration) || + !new.TLSInspectionConfiguration.Equal(old.TLSInspectionConfiguration) { + input := &networkfirewall.UpdateTLSInspectionConfigurationInput{} + response.Diagnostics.Append(fwflex.Expand(ctx, new, input)...) + if response.Diagnostics.HasError() { + return } - if err != nil { - return nil, "", err - } + input.UpdateToken = aws.String(old.UpdateToken.ValueString()) - return out, aws.ToString(out.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus), nil - } -} + output, err := conn.UpdateTLSInspectionConfigurationWithContext(ctx, input) -func findTLSInspectionConfigurationByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { - in := &networkfirewall.DescribeTLSInspectionConfigurationInput{ - TLSInspectionConfigurationArn: aws.String(arn), - } + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("updating NetworkFirewall TLS Inspection Configuration (%s)", new.ID.ValueString()), err.Error()) - out, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, in) - if err != nil { - if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: in, - } + return } - return nil, err - } + new.UpdateToken = fwflex.StringToFramework(ctx, output.UpdateToken) - if out == nil || out.TLSInspectionConfigurationResponse == nil { - return nil, tfresource.NewEmptyResultError(in) - } - - return out, nil -} + outputR, err := waitTLSInspectionConfigurationUpdated(ctx, conn, new.ID.ValueString(), r.CreateTimeout(ctx, new.Timeouts)) -func findTLSInspectionConfigurationByID(ctx context.Context, conn *networkfirewall.NetworkFirewall, id string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { - in := &networkfirewall.DescribeTLSInspectionConfigurationInput{ - TLSInspectionConfigurationArn: aws.String(id), - } + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("waiting for NetworkFirewall TLS Inspection Configuration (%s) update", new.ID.ValueString()), err.Error()) - out, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, in) - if err != nil { - if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { - return nil, &retry.NotFoundError{ - LastError: err, - LastRequest: in, - } + return } - return nil, err - } + // Set values for unknowns. + response.Diagnostics.Append(flattenDescribeTLSInspectionConfigurationOutput(ctx, &new, outputR)...) + if response.Diagnostics.HasError() { + return + } + } else { + new.CertificateAuthority = old.CertificateAuthority + new.Certificates = old.Certificates + new.UpdateToken = old.UpdateToken - if out == nil || out.TLSInspectionConfigurationResponse == nil { - return nil, tfresource.NewEmptyResultError(in) } - return out, nil + response.Diagnostics.Append(response.State.Set(ctx, &new)...) } -func flattenTLSInspectionConfiguration(ctx context.Context, tlsInspectionConfiguration *networkfirewall.TLSInspectionConfiguration) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: tlsInspectionConfigurationAttrTypes} - - if tlsInspectionConfiguration == nil { - return types.ListNull(elemType), diags - } - - flattenedConfig, d := flattenServerCertificateConfigurations(ctx, tlsInspectionConfiguration.ServerCertificateConfigurations) - diags.Append(d...) - - obj := map[string]attr.Value{ - "server_certificate_configurations": flattenedConfig, +func (r *tlsInspectionConfigurationResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data tlsInspectionConfigurationResourceModel + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return } - objVal, d := types.ObjectValue(tlsInspectionConfigurationAttrTypes, obj) - diags.Append(d...) - listVal, d := types.ListValue(elemType, []attr.Value{objVal}) - diags.Append(d...) - - return listVal, diags -} + conn := r.Meta().NetworkFirewallConn(ctx) -func flattenServerCertificateConfigurations(ctx context.Context, serverCertificateConfigurations []*networkfirewall.ServerCertificateConfiguration) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes} + _, err := conn.DeleteTLSInspectionConfigurationWithContext(ctx, &networkfirewall.DeleteTLSInspectionConfigurationInput{ + TLSInspectionConfigurationArn: aws.String(data.ID.ValueString()), + }) - if serverCertificateConfigurations == nil { - return types.ListNull(elemType), diags + if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { + return } - elems := []attr.Value{} - for _, serverCertificateConfiguration := range serverCertificateConfigurations { - checkCertRevocationStatus, d := flattenCheckCertificateRevocationStatus(ctx, serverCertificateConfiguration.CheckCertificateRevocationStatus) - diags.Append(d...) - scopes, d := flattenScopes(ctx, serverCertificateConfiguration.Scopes) - diags.Append(d...) - serverCertificates, d := flattenServerCertificates(ctx, serverCertificateConfiguration.ServerCertificates) - diags.Append(d...) - - obj := map[string]attr.Value{ - "certificate_authority_arn": flex.StringToFramework(ctx, serverCertificateConfiguration.CertificateAuthorityArn), - "check_certificate_revocation_status": checkCertRevocationStatus, - "scopes": scopes, - "server_certificates": serverCertificates, - } + if err != nil { + response.Diagnostics.AddError(fmt.Sprintf("deleting NetworkFirewall TLS Inspection Configuration (%s)", data.ID.ValueString()), err.Error()) - objVal, d := types.ObjectValue(serverCertificateConfigurationAttrTypes, obj) - diags.Append(d...) - elems = append(elems, objVal) + return } - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) + if _, err := waitTLSInspectionConfigurationDeleted(ctx, conn, data.ID.ValueString(), r.DeleteTimeout(ctx, data.Timeouts)); err != nil { + response.Diagnostics.AddError(fmt.Sprintf("waiting for NetworkFirewall TLS Inspection Configuration (%s) delete", data.ID.ValueString()), err.Error()) - return listVal, diags -} - -func flattenCheckCertificateRevocationStatus(ctx context.Context, checkCertificateRevocationStatus *networkfirewall.CheckCertificateRevocationStatusActions) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes} - - if checkCertificateRevocationStatus == nil { - return types.ListNull(elemType), diags - } - - obj := map[string]attr.Value{ - "revoked_status_action": flex.StringToFramework(ctx, checkCertificateRevocationStatus.RevokedStatusAction), - "unknown_status_action": flex.StringToFramework(ctx, checkCertificateRevocationStatus.UnknownStatusAction), + return } - - flattenedCheckCertificateRevocationStatus, d := types.ObjectValue(checkCertificateRevocationStatusAttrTypes, obj) - diags.Append(d...) - - listVal, d := types.ListValue(elemType, []attr.Value{flattenedCheckCertificateRevocationStatus}) - diags.Append(d...) - - return listVal, diags } -func flattenServerCertificates(ctx context.Context, serverCertificateList []*networkfirewall.ServerCertificate) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: serverCertificatesAttrTypes} - - if len(serverCertificateList) == 0 { - return types.ListNull(elemType), diags +func findTLSInspectionConfigurationByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { + input := &networkfirewall.DescribeTLSInspectionConfigurationInput{ + TLSInspectionConfigurationArn: aws.String(arn), } - elems := []attr.Value{} - for _, serverCertificate := range serverCertificateList { - if serverCertificate == nil { - continue - } - obj := map[string]attr.Value{ - "resource_arn": flex.StringToFramework(ctx, serverCertificate.ResourceArn), - } - - flattenedServerCertificate, d := types.ObjectValue(serverCertificatesAttrTypes, obj) + output, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, input) - diags.Append(d...) - elems = append(elems, flattenedServerCertificate) + if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } } - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) - - return listVal, diags -} - -func flattenTLSCertificate(ctx context.Context, certificate *networkfirewall.TlsCertificateData) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: certificatesAttrTypes} - - if certificate == nil { - return types.ListNull(elemType), diags + if err != nil { + return nil, err } - obj := map[string]attr.Value{ - "certificate_arn": flex.StringToFramework(ctx, certificate.CertificateArn), - "certificate_serial": flex.StringToFramework(ctx, certificate.CertificateSerial), - "status": flex.StringToFramework(ctx, certificate.Status), - "status_message": flex.StringToFramework(ctx, certificate.StatusMessage), + if output == nil || output.TLSInspectionConfigurationResponse == nil { + return nil, tfresource.NewEmptyResultError(input) } - objVal, d := types.ObjectValue(certificatesAttrTypes, obj) - diags.Append(d...) - listVal, d := types.ListValue(elemType, []attr.Value{objVal}) - diags.Append(d...) - - return listVal, diags + return output, nil } -func flattenScopes(ctx context.Context, scopes []*networkfirewall.ServerCertificateScope) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: scopeAttrTypes} - - if len(scopes) == 0 { - return types.ListNull(elemType), diags - } +func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := findTLSInspectionConfigurationByARN(ctx, conn, arn) - elems := []attr.Value{} - for _, scope := range scopes { - if scope == nil { - continue + if tfresource.NotFound(err) { + return nil, "", nil } - destinationPorts, d := flattenPortRange(ctx, scope.DestinationPorts) - diags.Append(d...) - destinations, d := flattenSourceDestinations(ctx, scope.Destinations) - diags.Append(d...) - protocols, d := flattenProtocols(scope.Protocols) - diags.Append(d...) - sourcePorts, d := flattenPortRange(ctx, scope.SourcePorts) - diags.Append(d...) - sources, d := flattenSourceDestinations(ctx, scope.Sources) - diags.Append(d...) - - obj := map[string]attr.Value{ - "destination_ports": destinationPorts, - "destinations": destinations, - "protocols": protocols, - "source_ports": sourcePorts, - "sources": sources, + if err != nil { + return nil, "", err } - objVal, d := types.ObjectValue(scopeAttrTypes, obj) - diags.Append(d...) - elems = append(elems, objVal) + return output, aws.StringValue(output.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus), nil } - - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) - - return listVal, diags } -func flattenProtocols(list []*int64) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.Int64Type +const ( + resourceStatusPending = "PENDING" +) - if len(list) == 0 { - return types.ListNull(elemType), diags - } +func statusTLSInspectionConfigurationCertificates(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { + return func() (interface{}, string, error) { + output, err := findTLSInspectionConfigurationByARN(ctx, conn, arn) - elems := []attr.Value{} - for _, item := range list { - if item == nil { - continue + if tfresource.NotFound(err) { + return nil, "", nil } - objVal := types.Int64Value(*item) - - elems = append(elems, objVal) - } - - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) - - return listVal, diags -} - -func flattenSourceDestinations(ctx context.Context, destinations []*networkfirewall.Address) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: sourceDestinationAttrTypes} - - if len(destinations) == 0 { - return types.ListNull(elemType), diags - } - - elems := []attr.Value{} - for _, destination := range destinations { - if destination == nil { - continue + if err != nil { + return nil, "", err } - obj := map[string]attr.Value{ - "address_definition": flex.StringToFramework(ctx, destination.AddressDefinition), + certificates := output.TLSInspectionConfigurationResponse.Certificates + certificateAuthority := output.TLSInspectionConfigurationResponse.CertificateAuthority + + // The API does not immediately return data for certificates and certificate authority even when the resource status is "ACTIVE", + // which causes unexpected diffs when reading. This sets the status to "PENDING" until either the certificates or the certificate + // authority is populated (the API will always return at least one of the two). + if status := aws.StringValue(output.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus); status == networkfirewall.ResourceStatusActive && (certificates != nil || certificateAuthority != nil) { + return output, status, nil } - objVal, d := types.ObjectValue(sourceDestinationAttrTypes, obj) - diags.Append(d...) - elems = append(elems, objVal) + return output, resourceStatusPending, nil } - - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) - - return listVal, diags } -func flattenPortRange(ctx context.Context, ranges []*networkfirewall.PortRange) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: portRangeAttrTypes} - - if len(ranges) == 0 { - return types.ListNull(elemType), diags +func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{resourceStatusPending}, + Target: []string{networkfirewall.ResourceStatusActive}, + Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), + Timeout: timeout, } - elems := []attr.Value{} - for _, portRange := range ranges { - if portRange == nil { - continue - } - - obj := map[string]attr.Value{ - "from_port": flex.Int64ToFramework(ctx, portRange.FromPort), - "to_port": flex.Int64ToFramework(ctx, portRange.ToPort), - } - objVal, d := types.ObjectValue(portRangeAttrTypes, obj) - diags.Append(d...) + outputRaw, err := stateConf.WaitForStateContext(ctx) - elems = append(elems, objVal) + if output, ok := outputRaw.(*networkfirewall.DescribeTLSInspectionConfigurationOutput); ok { + return output, err } - listVal, d := types.ListValue(elemType, elems) - diags.Append(d...) - - return listVal, diags + return nil, err } -func flattenTLSEncryptionConfiguration(ctx context.Context, encryptionConfiguration *networkfirewall.EncryptionConfiguration) (types.List, diag.Diagnostics) { - var diags diag.Diagnostics - elemType := types.ObjectType{AttrTypes: encryptionConfigurationAttrTypes} - - if encryptionConfiguration == nil { - return types.ListNull(elemType), diags - } - - obj := map[string]attr.Value{ - "key_id": flex.StringToFramework(ctx, encryptionConfiguration.KeyId), - "type": flex.StringToFramework(ctx, encryptionConfiguration.Type), +func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{resourceStatusPending}, + Target: []string{networkfirewall.ResourceStatusActive}, + Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), + Timeout: timeout, } - objVal, d := types.ObjectValue(encryptionConfigurationAttrTypes, obj) - diags.Append(d...) - - listVal, d := types.ListValue(elemType, []attr.Value{objVal}) - diags.Append(d...) - return listVal, diags -} - -// TODO: add note explaining why not using existing expandEncryptionConfiguration() -func expandTLSEncryptionConfiguration(tfList []encryptionConfigurationData) *networkfirewall.EncryptionConfiguration { - if len(tfList) == 0 { - return nil - } + outputRaw, err := stateConf.WaitForStateContext(ctx) - tfObj := tfList[0] - apiObject := &networkfirewall.EncryptionConfiguration{ - KeyId: aws.String(tfObj.KeyId.ValueString()), - Type: aws.String(tfObj.Type.ValueString()), + if output, ok := outputRaw.(*networkfirewall.DescribeTLSInspectionConfigurationOutput); ok { + return output, err } - return apiObject + return nil, err } -func expandTLSInspectionConfiguration(ctx context.Context, tfList []tlsInspectionConfigurationData) *networkfirewall.TLSInspectionConfiguration { - var diags diag.Diagnostics - - if len(tfList) == 0 { - return nil +func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { + stateConf := &retry.StateChangeConf{ + Pending: []string{networkfirewall.ResourceStatusActive, networkfirewall.ResourceStatusDeleting}, + Target: []string{}, + Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), + Timeout: timeout, } - tfObj := tfList[0] - - var serverCertConfig []serverCertificateConfigurationsData - diags.Append(tfObj.ServerCertificateConfiguration.ElementsAs(ctx, &serverCertConfig, false)...) + outputRaw, err := stateConf.WaitForStateContext(ctx) - apiObject := &networkfirewall.TLSInspectionConfiguration{ - ServerCertificateConfigurations: expandServerCertificateConfigurations(ctx, serverCertConfig), + if output, ok := outputRaw.(*networkfirewall.DescribeTLSInspectionConfigurationOutput); ok { + return output, err } - return apiObject + return nil, err } -func expandServerCertificateConfigurations(ctx context.Context, tfList []serverCertificateConfigurationsData) []*networkfirewall.ServerCertificateConfiguration { +func flattenDescribeTLSInspectionConfigurationOutput(ctx context.Context, data *tlsInspectionConfigurationResourceModel, apiObject *networkfirewall.DescribeTLSInspectionConfigurationOutput) diag.Diagnostics { var diags diag.Diagnostics - var apiObject []*networkfirewall.ServerCertificateConfiguration - - for _, item := range tfList { - conf := &networkfirewall.ServerCertificateConfiguration{} - - // Configure CertificateAuthorityArn for outbound SSL/TLS inspection - if !item.CertificateAuthorityArn.IsNull() { - conf.CertificateAuthorityArn = aws.String(item.CertificateAuthorityArn.ValueString()) - } - if !item.CheckCertificateRevocationsStatus.IsNull() { - var certificateRevocationStatus []checkCertificateRevocationStatusData - diags.Append(item.CheckCertificateRevocationsStatus.ElementsAs(ctx, &certificateRevocationStatus, false)...) - conf.CheckCertificateRevocationStatus = expandCheckCertificateRevocationStatus(certificateRevocationStatus) - } - if !item.Scope.IsNull() { - var scopesList []scopeData - diags.Append(item.Scope.ElementsAs(ctx, &scopesList, false)...) - conf.Scopes = expandScopes(ctx, scopesList) - } - // Configure ServerCertificates for inbound SSL/TLS inspection - if !item.ServerCertificates.IsNull() { - var serverCertificates []serverCertificatesData - diags.Append(item.ServerCertificates.ElementsAs(ctx, &serverCertificates, false)...) - conf.ServerCertificates = expandServerCertificates(serverCertificates) - } - - apiObject = append(apiObject, conf) - } - - return apiObject -} - -func expandCheckCertificateRevocationStatus(tfList []checkCertificateRevocationStatusData) *networkfirewall.CheckCertificateRevocationStatusActions { - if len(tfList) == 0 { - return nil - } - - tfObj := tfList[0] - apiObject := &networkfirewall.CheckCertificateRevocationStatusActions{ - RevokedStatusAction: aws.String(tfObj.RevokedStatusAction.ValueString()), - UnknownStatusAction: aws.String(tfObj.UnknownStatusAction.ValueString()), + d := fwflex.Flatten(ctx, apiObject.TLSInspectionConfigurationResponse, &data) + diags.Append(d...) + if diags.HasError() { + return diags } - return apiObject -} - -func expandServerCertificates(tfList []serverCertificatesData) []*networkfirewall.ServerCertificate { - var apiObject []*networkfirewall.ServerCertificate - for _, item := range tfList { - conf := &networkfirewall.ServerCertificate{ - ResourceArn: aws.String(item.ResourceARN.ValueString()), - } - - apiObject = append(apiObject, conf) + var tlsInspectionConfigurationData tlsInspectionConfigurationModel + d = fwflex.Flatten(ctx, apiObject.TLSInspectionConfiguration, &tlsInspectionConfigurationData) + diags.Append(d...) + if diags.HasError() { + return diags } - return apiObject -} -func expandScopes(ctx context.Context, tfList []scopeData) []*networkfirewall.ServerCertificateScope { - var diags diag.Diagnostics - var apiObject []*networkfirewall.ServerCertificateScope - - for _, tfObj := range tfList { - item := &networkfirewall.ServerCertificateScope{} - if !tfObj.Protocols.IsNull() { - protocols := []*int64{} - diags.Append(tfObj.Protocols.ElementsAs(ctx, &protocols, false)...) - item.Protocols = protocols - } - if !tfObj.DestinationPorts.IsNull() { - var destinationPorts []portRangeData - diags.Append(tfObj.DestinationPorts.ElementsAs(ctx, &destinationPorts, false)...) - item.DestinationPorts = expandPortRange(destinationPorts) - } - if !tfObj.Destinations.IsNull() { - var destinations []sourceDestinationData - diags.Append(tfObj.Destinations.ElementsAs(ctx, &destinations, false)...) - item.Destinations = expandSourceDestinations(destinations) - } - if !tfObj.SourcePorts.IsNull() { - var sourcePorts []portRangeData - diags.Append(tfObj.SourcePorts.ElementsAs(ctx, &sourcePorts, false)...) - item.SourcePorts = expandPortRange(sourcePorts) - } - if !tfObj.Sources.IsNull() { - var sources []sourceDestinationData - diags.Append(tfObj.Sources.ElementsAs(ctx, &sources, false)...) - item.Sources = expandSourceDestinations(sources) - } - apiObject = append(apiObject, item) + tlsInspectionConfiguration, d := fwtypes.NewListNestedObjectValueOfPtr(ctx, &tlsInspectionConfigurationData) + diags.Append(d...) + if diags.HasError() { + return diags } + data.TLSInspectionConfiguration = tlsInspectionConfiguration - return apiObject + return diags } -func expandPortRange(tfList []portRangeData) []*networkfirewall.PortRange { - var apiObject []*networkfirewall.PortRange - - for _, tfObj := range tfList { - item := &networkfirewall.PortRange{ - FromPort: aws.Int64(tfObj.FromPort.ValueInt64()), - ToPort: aws.Int64(tfObj.ToPort.ValueInt64()), - } - apiObject = append(apiObject, item) - } - - return apiObject +type tlsInspectionConfigurationResourceModel struct { + CertificateAuthority fwtypes.ListNestedObjectValueOf[tlsCertificateDataModel] `tfsdk:"certificate_authority"` + Certificates fwtypes.ListNestedObjectValueOf[tlsCertificateDataModel] `tfsdk:"certificates"` + Description types.String `tfsdk:"description"` + EncryptionConfiguration fwtypes.ListNestedObjectValueOf[encryptionConfigurationModel] `tfsdk:"encryption_configuration"` + ID types.String `tfsdk:"id"` + NumberOfAssociations types.Int64 `tfsdk:"number_of_associations"` + Tags types.Map `tfsdk:"tags"` + TagsAll types.Map `tfsdk:"tags_all"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + TLSInspectionConfiguration fwtypes.ListNestedObjectValueOf[tlsInspectionConfigurationModel] `tfsdk:"tls_inspection_configuration"` + TLSInspectionConfigurationARN types.String `tfsdk:"arn"` + TLSInspectionConfigurationID types.String `tfsdk:"tls_inspection_configuration_id"` + TLSInspectionConfigurationName types.String `tfsdk:"name"` + UpdateToken types.String `tfsdk:"update_token"` } -func expandSourceDestinations(tfList []sourceDestinationData) []*networkfirewall.Address { - var apiObject []*networkfirewall.Address - - for _, tfObj := range tfList { - item := &networkfirewall.Address{ - AddressDefinition: aws.String(tfObj.AddressDefinition.ValueString()), - } - apiObject = append(apiObject, item) - } +func (model *tlsInspectionConfigurationResourceModel) InitFromID() error { + model.TLSInspectionConfigurationARN = model.ID - return apiObject + return nil } -type resourceTLSInspectionConfigurationData struct { - ARN types.String `tfsdk:"arn"` - EncryptionConfiguration types.List `tfsdk:"encryption_configuration"` - Certificates fwtypes.ListNestedObjectValueOf[certificatesData] `tfsdk:"certificates"` - CertificateAuthority types.List `tfsdk:"certificate_authority"` - Description types.String `tfsdk:"description"` - ID types.String `tfsdk:"id"` - LastModifiedTime types.String `tfsdk:"last_modified_time"` - Name types.String `tfsdk:"name"` - NumberOfAssociations types.Int64 `tfsdk:"number_of_associations"` - Status types.String `tfsdk:"status"` - TLSInspectionConfiguration types.List `tfsdk:"tls_inspection_configuration"` - Timeouts timeouts.Value `tfsdk:"timeouts"` - UpdateToken types.String `tfsdk:"update_token"` +func (model *tlsInspectionConfigurationResourceModel) setID() { + model.ID = model.TLSInspectionConfigurationARN } -type encryptionConfigurationData struct { +type encryptionConfigurationModel struct { + KeyID fwtypes.ARN `tfsdk:"key_id"` Type types.String `tfsdk:"type"` - KeyId types.String `tfsdk:"key_id"` -} - -type certificatesData struct { - CertificateArn types.String `tfsdk:"certificate_arn"` - CertificateSerial types.String `tfsdk:"certificate_serial"` - Status types.String `tfsdk:"status"` - StatusMessage types.String `tfsdk:"status_message"` -} - -type tlsInspectionConfigurationData struct { - ServerCertificateConfiguration types.List `tfsdk:"server_certificate_configurations"` } -type serverCertificateConfigurationsData struct { - CertificateAuthorityArn types.String `tfsdk:"certificate_authority_arn"` - CheckCertificateRevocationsStatus types.List `tfsdk:"check_certificate_revocation_status"` - Scope types.List `tfsdk:"scopes"` - ServerCertificates types.List `tfsdk:"server_certificates"` +type tlsInspectionConfigurationModel struct { + ServerCertificateConfigurations fwtypes.ListNestedObjectValueOf[serverCertificateConfigurationModel] `tfsdk:"server_certificate_configuration"` } -type scopeData struct { - DestinationPorts types.List `tfsdk:"destination_ports"` - Destinations types.List `tfsdk:"destinations"` - Protocols types.List `tfsdk:"protocols"` - SourcePorts types.List `tfsdk:"source_ports"` - Sources types.List `tfsdk:"sources"` +type serverCertificateConfigurationModel struct { + CertificateAuthorityARN fwtypes.ARN `tfsdk:"certificate_authority_arn"` + CheckCertificateRevocationsStatus fwtypes.ListNestedObjectValueOf[checkCertificateRevocationStatusActionsModel] `tfsdk:"check_certificate_revocation_status"` + Scope fwtypes.ListNestedObjectValueOf[serverCertificateScopeModel] `tfsdk:"scope"` + ServerCertificates fwtypes.ListNestedObjectValueOf[serverCertificateModel] `tfsdk:"server_certificate"` } -type sourceDestinationData struct { - AddressDefinition types.String `tfsdk:"address_definition"` -} - -type portRangeData struct { - FromPort types.Int64 `tfsdk:"from_port"` - ToPort types.Int64 `tfsdk:"to_port"` -} - -type checkCertificateRevocationStatusData struct { +type checkCertificateRevocationStatusActionsModel struct { RevokedStatusAction types.String `tfsdk:"revoked_status_action"` UnknownStatusAction types.String `tfsdk:"unknown_status_action"` } -type serverCertificatesData struct { - ResourceARN types.String `tfsdk:"resource_arn"` -} - -var certificatesAttrTypes = map[string]attr.Type{ - "certificate_arn": types.StringType, - "certificate_serial": types.StringType, - "status": types.StringType, - "status_message": types.StringType, +type serverCertificateScopeModel struct { + DestinationPorts fwtypes.ListNestedObjectValueOf[portRangeModel] `tfsdk:"destination_ports"` + Destinations fwtypes.ListNestedObjectValueOf[addressModel] `tfsdk:"destination"` + SourcePorts fwtypes.ListNestedObjectValueOf[portRangeModel] `tfsdk:"source_ports"` + Protocols fwtypes.SetValueOf[types.Int64] `tfsdk:"protocols"` + Sources fwtypes.ListNestedObjectValueOf[addressModel] `tfsdk:"source"` } -var encryptionConfigurationAttrTypes = map[string]attr.Type{ - "type": types.StringType, - "key_id": types.StringType, -} - -var tlsInspectionConfigurationAttrTypes = map[string]attr.Type{ - "server_certificate_configurations": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificateConfigurationAttrTypes}}, +type portRangeModel struct { + FromPort types.Int64 `tfsdk:"from_port"` + ToPort types.Int64 `tfsdk:"to_port"` } -var serverCertificateConfigurationAttrTypes = map[string]attr.Type{ - "certificate_authority_arn": types.StringType, - "check_certificate_revocation_status": types.ListType{ElemType: types.ObjectType{AttrTypes: checkCertificateRevocationStatusAttrTypes}}, - "scopes": types.ListType{ElemType: types.ObjectType{AttrTypes: scopeAttrTypes}}, - "server_certificates": types.ListType{ElemType: types.ObjectType{AttrTypes: serverCertificatesAttrTypes}}, +type addressModel struct { + AddressDefinition types.String `tfsdk:"address_definition"` } -var checkCertificateRevocationStatusAttrTypes = map[string]attr.Type{ - "revoked_status_action": types.StringType, - "unknown_status_action": types.StringType, +type serverCertificateModel struct { + ResourceARN fwtypes.ARN `tfsdk:"resource_arn"` } -var ( - scopeAttrTypes = map[string]attr.Type{ - "destination_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, - "destinations": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, - "protocols": types.ListType{ElemType: types.Int64Type}, - "source_ports": types.ListType{ElemType: types.ObjectType{AttrTypes: portRangeAttrTypes}}, - "sources": types.ListType{ElemType: types.ObjectType{AttrTypes: sourceDestinationAttrTypes}}, - } - - sourceDestinationAttrTypes = map[string]attr.Type{ - "address_definition": types.StringType, - } - - portRangeAttrTypes = map[string]attr.Type{ - "from_port": types.Int64Type, - "to_port": types.Int64Type, - } -) - -var serverCertificatesAttrTypes = map[string]attr.Type{ - "resource_arn": types.StringType, +type tlsCertificateDataModel struct { + CertificateARN types.String `tfsdk:"certificate_arn"` + CertificateSerial types.String `tfsdk:"certificate_serial"` + Status types.String `tfsdk:"status"` + StatusMessage types.String `tfsdk:"status_message"` } diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index ecc982fc484..535f03df2a2 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -5,22 +5,19 @@ package networkfirewall_test import ( "context" - "errors" "fmt" "os" "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go/service/networkfirewall" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/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" - "github.com/hashicorp/terraform-provider-aws/internal/errs" tfnetworkfirewall "github.com/hashicorp/terraform-provider-aws/internal/service/networkfirewall" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -57,26 +54,25 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "description", "test"), - resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ "key_id": "AWS_OWNED_KMS_KEY", "type": "AWS_OWNED_KMS_KEY", }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", caCertificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", caCertificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, @@ -91,26 +87,25 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "description", "test"), - resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ "key_id": "AWS_OWNED_KMS_KEY", "type": "AWS_OWNED_KMS_KEY", }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "10.0.0.0/8"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "8080"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "10.0.0.0/8"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "1024"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65534"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", caCertificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "PASS"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "8080"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "1024"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65534"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", caCertificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "REJECT"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, @@ -149,25 +144,23 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "description", "test"), - resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ "key_id": "AWS_OWNED_KMS_KEY", "type": "AWS_OWNED_KMS_KEY", }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", ca), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", ca), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, @@ -207,23 +200,21 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressWithEncryptionConfig testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "description", "test"), - resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, "arn"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.certificate_authority_arn", ca), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "1"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", ca), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, @@ -262,23 +253,21 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "description", "test"), - resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ "key_id": "AWS_OWNED_KMS_KEY", "type": "AWS_OWNED_KMS_KEY", }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), @@ -320,21 +309,19 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfi testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "description", "test"), - resource.TestCheckResourceAttrSet(resourceName, "last_modified_time"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, "arn"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.server_certificates.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destinations.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.sources.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.from_port", "0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.scopes.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configurations.0.check_certificate_revocation_status.#", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "0"), resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), @@ -389,45 +376,39 @@ func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource continue } - input := &networkfirewall.DescribeTLSInspectionConfigurationInput{ - TLSInspectionConfigurationArn: aws.String(rs.Primary.Attributes["arn"]), - } - _, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, input) - if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { - return nil + _, err := tfnetworkfirewall.FindTLSInspectionConfigurationByARN(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue } + if err != nil { - return create.Error(names.NetworkFirewall, create.ErrActionCheckingDestroyed, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, err) + return err } - return create.Error(names.NetworkFirewall, create.ErrActionCheckingDestroyed, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, errors.New("not destroyed")) + return fmt.Errorf("NetworkFirewall TLS Inspection Configuration %s still exists", rs.Primary.ID) } return nil } } -func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, name string, tlsinspectionconfiguration *networkfirewall.DescribeTLSInspectionConfigurationOutput) resource.TestCheckFunc { +func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, n string, v *networkfirewall.DescribeTLSInspectionConfigurationOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[name] + rs, ok := s.RootModule().Resources[n] if !ok { - return create.Error(names.NetworkFirewall, create.ErrActionCheckingExistence, tfnetworkfirewall.ResNameTLSInspectionConfiguration, name, errors.New("not found")) - } - - if rs.Primary.ID == "" { - return create.Error(names.NetworkFirewall, create.ErrActionCheckingExistence, tfnetworkfirewall.ResNameTLSInspectionConfiguration, name, errors.New("not set")) + return fmt.Errorf("Not found: %s", n) } conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) - resp, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, &networkfirewall.DescribeTLSInspectionConfigurationInput{ - TLSInspectionConfigurationArn: aws.String(rs.Primary.Attributes["arn"]), - }) + + output, err := tfnetworkfirewall.FindTLSInspectionConfigurationByARN(ctx, conn, rs.Primary.ID) if err != nil { - return create.Error(names.NetworkFirewall, create.ErrActionCheckingExistence, tfnetworkfirewall.ResNameTLSInspectionConfiguration, rs.Primary.ID, err) + return err } - *tlsinspectionconfiguration = *resp + *v = *output return nil } @@ -443,29 +424,29 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { - server_certificate_configurations { + server_certificate_configuration { certificate_authority_arn = %[3]q check_certificate_revocation_status { revoked_status_action = "REJECT" unknown_status_action = "PASS" } - server_certificates { + server_certificate { resource_arn = %[2]q } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -485,29 +466,29 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { - server_certificate_configurations { + server_certificate_configuration { certificate_authority_arn = %[3]q check_certificate_revocation_status { revoked_status_action = "PASS" unknown_status_action = "REJECT" } - server_certificates { + server_certificate { resource_arn = %[2]q } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 8080 } - destinations { + destination { address_definition = "10.0.0.0/8" } source_ports { from_port = 1024 to_port = 65534 } - sources { + source { address_definition = "10.0.0.0/8" } } @@ -527,24 +508,24 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { - server_certificate_configurations { - server_certificates { + server_certificate_configuration { + server_certificate { resource_arn = %[2]q } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -573,24 +554,24 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { type = "CUSTOMER_KMS" } tls_inspection_configuration { - server_certificate_configurations { - server_certificates { + server_certificate_configuration { + server_certificate { resource_arn = %[2]q } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -610,26 +591,26 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { - server_certificate_configurations { + server_certificate_configuration { certificate_authority_arn = %[2]q check_certificate_revocation_status { revoked_status_action = "REJECT" unknown_status_action = "PASS" } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -649,26 +630,26 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { type = "CUSTOMER_KMS" } tls_inspection_configuration { - server_certificate_configurations { + server_certificate_configuration { certificate_authority_arn = %[2]q check_certificate_revocation_status { revoked_status_action = "REJECT" unknown_status_action = "PASS" } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } diff --git a/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown index 94d46f32afe..0e071179a9f 100644 --- a/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown +++ b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown @@ -5,6 +5,7 @@ page_title: "AWS: aws_networkfirewall_tls_inspection_configuration" description: |- Terraform resource for managing an AWS Network Firewall TLS Inspection Configuration. --- + # Resource: aws_networkfirewall_tls_inspection_configuration Terraform resource for managing an AWS Network Firewall TLS Inspection Configuration. @@ -24,24 +25,24 @@ resource "aws_networkfirewall_tls_inspection_configuration" "example" { type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { - server_certificate_configurations { - server_certificates { + server_certificate_configuration { + server_certificate { resource_arn = aws_acm_certificate.example_1.arn } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -61,26 +62,26 @@ resource "aws_networkfirewall_tls_inspection_configuration" "example" { type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { - server_certificate_configurations { + server_certificate_configuration { certificate_authority_arn = aws_acm_certificate.example_1.arn check_certificate_revocation_status { revoked_status_action = "REJECT" unknown_status_action = "PASS" } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -105,8 +106,8 @@ resource "aws_networkfirewall_tls_inspection_configuration" "example" { type = "CUSTOMER_KMS" } tls_inspection_configuration { - server_certificate_configurations { - server_certificates { + server_certificate_configuration { + server_certificate { resource_arn = aws_acm_certificate.example_1.arn } scopes { @@ -153,20 +154,20 @@ resource "aws_networkfirewall_tls_inspection_configuration" "example" { revoked_status_action = "REJECT" unknown_status_action = "PASS" } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -186,29 +187,29 @@ resource "aws_networkfirewall_tls_inspection_configuration" "example" { type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { - server_certificate_configurations { + server_certificate_configuration { certificate_authority_arn = aws_acm_certificate.example_1.arn check_certificate_revocation_status { revoked_status_action = "REJECT" unknown_status_action = "PASS" } - server_certificates { + server_certificate { resource_arn = aws_acm_certificate.example_2.arn } - scopes { + scope { protocols = [6] destination_ports { from_port = 443 to_port = 443 } - destinations { + destination { address_definition = "0.0.0.0/0" } source_ports { from_port = 0 to_port = 65535 } - sources { + source { address_definition = "0.0.0.0/0" } } @@ -222,58 +223,48 @@ resource "aws_networkfirewall_tls_inspection_configuration" "example" { The following arguments are required: * `name` - (Required, Forces new resource) Descriptive name of the TLS inspection configuration. - * `tls_inspection_configuration` - (Required) TLS inspection configuration block. Detailed below. The following arguments are optional: * `description` - (Optional) Description of the TLS inspection configuration. - * `encryption_configuration` - (Optional) Encryption configuration block. Detailed below. ### Encryption Configuration -* `key_id` - (Optional) ID of the Amazon Web Services Key Management Service (KMS) customer managed key. You can use any of the key identifiers that KMS supports, unless you're using a key that's managed by another account. If you're using a key managed by another account, then specify the key ARN. +* `key_id` - (Optional) ARN of the Amazon Web Services Key Management Service (KMS) customer managed key. * `type` - (Optional) Type of KMS key to use for encryption of your Network Firewall resources. Valid values: `AWS_OWNED_KMS_KEY`, `CUSTOMER_KMS`. ### TLS Inspection Configuration -* `server_certificate_configurations` - (Required) Server certificate configurations that are associated with the TLS configuration. Detailed below. +* `server_certificate_configuration` - (Required) Server certificate configurations that are associated with the TLS configuration. Detailed below. -### Server Certificate Configurations +### Server Certificate Configuration -The `server_certificate_configurations` block supports the following arguments: +The `server_certificate_configuration` block supports the following arguments: * `certificate_authority_arn` - (Optional) ARN of the imported certificate authority (CA) certificate within Certificate Manager (ACM) to use for outbound SSL/TLS inspection. See [Using SSL/TLS certificates with TLS inspection configurations](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html) for limitations on CA certificates. - * `check_certificate_revocation_status` (Optional) - Check Certificate Revocation Status block. Detailed below. - -* `scopes` (Required) - Scopes block. Detailed below. - -* `server_certificates` - (Optional) Server certificates to use for inbound SSL/TLS inspection. See [Using SSL/TLS certificates with TLS inspection configurations](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html). +* `scope` (Required) - Scope block. Detailed below. +* `server_certificate` - (Optional) Server certificates to use for inbound SSL/TLS inspection. See [Using SSL/TLS certificates with TLS inspection configurations](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html). ### Check Certificate Revocation Status The `check_certificate_revocation_status` block supports the following arguments: -~> **NOTE To check the certificate revocation status, you must also specify a `certificate_authority_arn` in `server_certificate_configurations`. +~> **NOTE To check the certificate revocation status, you must also specify a `certificate_authority_arn` in `server_certificate_configuration`. `revoked_status_action` - (Optional) how Network Firewall processes traffic when it determines that the certificate presented by the server in the SSL/TLS connection has a revoked status. See [Checking certificate revocation status](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html#tls-inspection-check-certificate-revocation-status) for details. Valid values: `PASS`, `DROP`, `REJECT`. - `unknown_status_action` - (Optional) How Network Firewall processes traffic when it determines that the certificate presented by the server in the SSL/TLS connection has an unknown status, or a status that cannot be determined for any other reason, including when the service is unable to connect to the OCSP and CRL endpoints for the certificate. See [Checking certificate revocation status](https://docs.aws.amazon.com/network-firewall/latest/developerguide/tls-inspection-certificate-requirements.html#tls-inspection-check-certificate-revocation-status) for details. Valid values: `PASS`, `DROP`, `REJECT`. ### Scopes -The `scopes` block supports the following arguments: - -* `destinations` - (Optional) Set of configuration blocks describing the destination IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any destination address. See [Destination](#destination) below for details. +The `scope` block supports the following arguments: +* `destination` - (Optional) Set of configuration blocks describing the destination IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any destination address. See [Destination](#destination) below for details. * `destination_ports` - (Optional) Set of configuration blocks describing the destination ports to inspect for. If not specified, this matches with any destination port. See [Destination Ports](#destination-ports) below for details. - * `protocols` - (Optional) Set of protocols to inspect for, specified using the protocol's assigned internet protocol number (IANA). Network Firewall currently supports TCP only. Valid values: `6` - -* `sources` - (Optional) Set of configuration blocks describing the source IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any source address. See [Source](#source) below for details. - +* `source` - (Optional) Set of configuration blocks describing the source IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any source address. See [Source](#source) below for details. * `source_ports` - (Optional) Set of configuration blocks describing the source ports to inspect for. If not specified, this matches with any source port. See [Source Ports](#source-ports) below for details. ### Destination @@ -287,7 +278,6 @@ The `destination` block supports the following argument: The `destination_ports` block supports the following arguments: * `from_ports` - (Required) The lower limit of the port range. This must be less than or equal to the `to_port`. - * `to_ports` - (Optional) The upper limit of the port range. This must be greater than or equal to the `from_port`. ### Source @@ -301,12 +291,11 @@ The `source` block supports the following argument: The `source_ports` block supports the following arguments: * `from_port` - (Required) The lower limit of the port range. This must be less than or equal to the `to_port`. - * `to_port` - (Optional) The upper limit of the port range. This must be greater than or equal to the `from_port`. ### Server Certificates -The `server_certificates` block supports the following arguments: +The `server_certificate` block supports the following arguments: * `resource_arn` - (Optional) ARN of the Certificate Manager SSL/TLS server certificate that's used for inbound SSL/TLS inspection. @@ -317,9 +306,8 @@ This resource exports the following attributes in addition to the arguments abov * `arn` - ARN of the TLS Inspection Configuration. * `certificate_authority` - Certificate Manager certificate block. See [Certificate Authority](#certificate-authority) below for details. * `certificates` - List of certificate blocks describing certificates associated with the TLS inspection configuration. See [Certificates](#certificates) below for details. -* `last_modified_time` - Last time that the TLS inspection configuration was changed, in UTC [RFC3339](https://tools.ietf.org/html/rfc3339#section-5.8) format(for example, YYYY-MM-DDTHH:MM:SSZ). * `number_of_associations` - Number of firewall policies that use this TLS inspection configuration. -* `status` - Current status of a TLS inspection configuration. +* `tls_inspection_configuration_id` - A unique identifier for the TLS inspection configuration. * `update_token` - String token used when updating the rule group. ### Certificate Authority @@ -344,9 +332,9 @@ The `certificates` block exports the following attributes: [Configuration options](https://developer.hashicorp.com/terraform/language/resources/syntax#operation-timeouts): -* `create` - (Default `60m`) -* `update` - (Default `180m`) -* `delete` - (Default `90m`) +* `create` - (Default `30m`) +* `update` - (Default `30m`) +* `delete` - (Default `30m`) ## Import From 65f6f464794e956b4477f5fc505ecd60b416ee75 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 18 Jun 2024 17:02:57 -0400 Subject: [PATCH 28/68] Run 'make fix-constants PKG=networkfirewall'. --- .../tls_inspection_configuration.go | 14 +-- .../tls_inspection_configuration_test.go | 88 +++++++++---------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index a92f1bfe14c..e2d1c30184f 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -107,19 +107,19 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, }, Blocks: map[string]schema.Block{ - "encryption_configuration": schema.ListNestedBlock{ + names.AttrEncryptionConfiguration: schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[encryptionConfigurationModel](ctx), Validators: []validator.List{ listvalidator.SizeAtMost(1), }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ - "key_id": schema.StringAttribute{ + names.AttrKeyID: schema.StringAttribute{ CustomType: fwtypes.ARNType, Optional: true, Computed: true, }, - "type": schema.StringAttribute{ + names.AttrType: schema.StringAttribute{ Optional: true, Computed: true, Default: stringdefault.StaticString(networkfirewall.EncryptionTypeAwsOwnedKmsKey), @@ -130,7 +130,7 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, }, }, - "timeouts": timeouts.Block(ctx, timeouts.Opts{ + names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{ Create: true, Update: true, Delete: true, @@ -175,7 +175,7 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, }, }, - "scope": schema.ListNestedBlock{ + names.AttrScope: schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[serverCertificateScopeModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ @@ -208,7 +208,7 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, }, }, - "destination": schema.ListNestedBlock{ + names.AttrDestination: schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[addressModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ @@ -262,7 +262,7 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request CustomType: fwtypes.NewListNestedObjectTypeOf[serverCertificateModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ - "resource_arn": schema.StringAttribute{ + names.AttrResourceARN: schema.StringAttribute{ CustomType: fwtypes.ARNType, Optional: true, }, diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 535f03df2a2..3560115dba6 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -52,14 +52,14 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic Config: testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateArn, caCertificateArn), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - "key_id": "AWS_OWNED_KMS_KEY", - "type": "AWS_OWNED_KMS_KEY", + names.AttrKeyID: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), @@ -67,13 +67,13 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", caCertificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), - acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, { @@ -85,14 +85,14 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic Config: testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateArn, caCertificateArn), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - "key_id": "AWS_OWNED_KMS_KEY", - "type": "AWS_OWNED_KMS_KEY", + names.AttrKeyID: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "10.0.0.0/8"), @@ -103,10 +103,10 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "1024"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65534"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", caCertificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "PASS"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "REJECT"), - acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, { @@ -142,16 +142,16 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) Config: testAccTLSInspectionConfigurationConfig_egressBasic(rName, ca), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - "key_id": "AWS_OWNED_KMS_KEY", - "type": "AWS_OWNED_KMS_KEY", + names.AttrKeyID: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", ca), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), @@ -159,9 +159,9 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, { @@ -198,14 +198,14 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressWithEncryptionConfig Config: testAccTLSInspectionConfigurationConfig_egressWithEncryptionConfiguration(rName, ca), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), - resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, "arn"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, names.AttrARN), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", ca), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "1"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), @@ -213,9 +213,9 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressWithEncryptionConfig resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, { @@ -251,13 +251,13 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) Config: testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateArn), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - "key_id": "AWS_OWNED_KMS_KEY", - "type": "AWS_OWNED_KMS_KEY", + names.AttrKeyID: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), @@ -265,12 +265,12 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "0"), - resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), - resource.TestCheckResourceAttr(resourceName, "certificates.#", "1"), - acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "certificates.#", acctest.Ct1), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, { @@ -307,23 +307,23 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfi Config: testAccTLSInspectionConfigurationConfig_ingressWithEncryptionConfiguration(rName, certificateArn), Check: resource.ComposeTestCheckFunc( testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, "name", rName), - resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), - resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, "arn"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, names.AttrARN), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", "0"), - resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", "0"), - acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", acctest.Ct0), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, { From 1dbffd95d5ff2913c8dcb5e1afe08f8097bad405 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 18 Jun 2024 17:04:00 -0400 Subject: [PATCH 29/68] Run 'make fmt'. --- .../networkfirewall/tls_inspection_configuration_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 3560115dba6..9655250e2d4 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -59,7 +59,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), @@ -92,7 +92,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "10.0.0.0/8"), @@ -148,7 +148,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", ca), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), @@ -257,7 +257,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) resource.TestCheckResourceAttrSet(resourceName, "update_token"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", + names.AttrType: "AWS_OWNED_KMS_KEY", }), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), From 98f0a1d48a7dc442c4b492651e82be991cc6d768 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 18 Jun 2024 17:06:35 -0400 Subject: [PATCH 30/68] Fix golangci-lint 'whitespace'. --- internal/service/networkfirewall/tls_inspection_configuration.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index e2d1c30184f..e5c4953374d 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -416,7 +416,6 @@ func (r *tlsInspectionConfigurationResource) Update(ctx context.Context, request new.CertificateAuthority = old.CertificateAuthority new.Certificates = old.Certificates new.UpdateToken = old.UpdateToken - } response.Diagnostics.Append(response.State.Set(ctx, &new)...) From 1e2ae56ea44cca2c72fa54670f5db83893be8bb4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 14:10:29 -0400 Subject: [PATCH 31/68] AutoFlEx: Expand types.List(OfInt64). --- internal/framework/flex/auto_expand.go | 72 ++++++++++++++++ internal/framework/flex/auto_expand_test.go | 93 +++++++++++++++++++++ 2 files changed, 165 insertions(+) diff --git a/internal/framework/flex/auto_expand.go b/internal/framework/flex/auto_expand.go index 78a1213e3aa..c9cc9cd8aca 100644 --- a/internal/framework/flex/auto_expand.go +++ b/internal/framework/flex/auto_expand.go @@ -379,6 +379,10 @@ func (expander autoExpander) list(ctx context.Context, vFrom basetypes.ListValua } switch v.ElementType(ctx).(type) { + case basetypes.Int64Typable: + diags.Append(expander.listOfInt64(ctx, v, vTo)...) + return diags + case basetypes.StringTypable: diags.Append(expander.listOfString(ctx, v, vTo)...) return diags @@ -398,6 +402,69 @@ func (expander autoExpander) list(ctx context.Context, vFrom basetypes.ListValua return diags } +// listOfString copies a Plugin Framework ListOfInt64(ish) value to a compatible AWS API value. +func (expander autoExpander) listOfInt64(ctx context.Context, vFrom basetypes.ListValue, vTo reflect.Value) diag.Diagnostics { + var diags diag.Diagnostics + + switch vTo.Kind() { + case reflect.Slice: + switch tSliceElem := vTo.Type().Elem(); tSliceElem.Kind() { + case reflect.Int32, reflect.Int64: + // + // types.List(OfInt64) -> []int64 or []int32 + // + var to []int64 + diags.Append(vFrom.ElementsAs(ctx, &to, false)...) + if diags.HasError() { + return diags + } + + vals := reflect.MakeSlice(vTo.Type(), len(to), len(to)) + for i := 0; i < len(to); i++ { + vals.Index(i).SetInt(to[i]) + } + vTo.Set(vals) + return diags + + case reflect.Ptr: + switch tSliceElem.Elem().Kind() { + case reflect.Int32: + // + // types.List(OfInt64) -> []*int32. + // + var to []*int32 + diags.Append(vFrom.ElementsAs(ctx, &to, false)...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + + case reflect.Int64: + // + // types.List(OfInt64) -> []*int64. + // + var to []*int64 + diags.Append(vFrom.ElementsAs(ctx, &to, false)...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + } + } + + tflog.Info(ctx, "AutoFlex Expand; incompatible types", map[string]interface{}{ + "from list[%s]": vFrom.ElementType(ctx), + "to": vTo.Kind(), + }) + + return diags +} + // listOfString copies a Plugin Framework ListOfString(ish) value to a compatible AWS API value. func (expander autoExpander) listOfString(ctx context.Context, vFrom basetypes.ListValue, vTo reflect.Value) diag.Diagnostics { var diags diag.Diagnostics @@ -576,6 +643,11 @@ func (expander autoExpander) set(ctx context.Context, vFrom basetypes.SetValuabl } switch v.ElementType(ctx).(type) { + case basetypes.Int64Typable: + // TODO + // diags.Append(expander.setOfInt64(ctx, v, vTo)...) + return diags + case basetypes.StringTypable: diags.Append(expander.setOfString(ctx, v, vTo)...) return diags diff --git a/internal/framework/flex/auto_expand_test.go b/internal/framework/flex/auto_expand_test.go index a2762166407..fd6e037d358 100644 --- a/internal/framework/flex/auto_expand_test.go +++ b/internal/framework/flex/auto_expand_test.go @@ -779,6 +779,99 @@ func TestExpandStringEnum(t *testing.T) { runAutoExpandTestCases(ctx, t, testCases) } +func TestExpandListOfInt64(t *testing.T) { + t.Parallel() + + ctx := context.Background() + testCases := autoFlexTestCases{ + { + TestName: "valid value []int64", + Source: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]int64{}, + WantTarget: &[]int64{1, -1}, + }, + { + TestName: "empty value []int64", + Source: types.ListValueMust(types.Int64Type, []attr.Value{}), + Target: &[]int64{}, + WantTarget: &[]int64{}, + }, + { + TestName: "null value []int64", + Source: types.ListNull(types.Int64Type), + Target: &[]int64{}, + WantTarget: &[]int64{}, + }, + { + TestName: "valid value []*int64", + Source: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]*int64{}, + WantTarget: &[]*int64{aws.Int64(1), aws.Int64(-1)}, + }, + { + TestName: "empty value []*int64", + Source: types.ListValueMust(types.Int64Type, []attr.Value{}), + Target: &[]*int64{}, + WantTarget: &[]*int64{}, + }, + { + TestName: "null value []*int64", + Source: types.ListNull(types.Int64Type), + Target: &[]*int64{}, + WantTarget: &[]*int64{}, + }, + { + TestName: "valid value []int32", + Source: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]int32{}, + WantTarget: &[]int32{1, -1}, + }, + { + TestName: "empty value []int32", + Source: types.ListValueMust(types.Int64Type, []attr.Value{}), + Target: &[]int32{}, + WantTarget: &[]int32{}, + }, + { + TestName: "null value []int32", + Source: types.ListNull(types.Int64Type), + Target: &[]int32{}, + WantTarget: &[]int32{}, + }, + { + TestName: "valid value []*int32", + Source: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]*int32{}, + WantTarget: &[]*int32{aws.Int32(1), aws.Int32(-1)}, + }, + { + TestName: "empty value []*int32", + Source: types.ListValueMust(types.Int64Type, []attr.Value{}), + Target: &[]*int32{}, + WantTarget: &[]*int32{}, + }, + { + TestName: "null value []*int32", + Source: types.ListNull(types.Int64Type), + Target: &[]*int32{}, + WantTarget: &[]*int32{}, + }, + } + runAutoExpandTestCases(ctx, t, testCases) +} + func TestExpandListOfStringEnum(t *testing.T) { t.Parallel() From 88efb1b63ef8f5585545cbe48689efa64fcc09e4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 14:28:00 -0400 Subject: [PATCH 32/68] AutoFlEx: Expand types.Set(OfInt64). --- internal/framework/flex/auto_expand.go | 9 +- internal/framework/flex/auto_expand_test.go | 93 +++++++++++++++++++++ internal/framework/flex/autoflex.go | 9 ++ 3 files changed, 106 insertions(+), 5 deletions(-) diff --git a/internal/framework/flex/auto_expand.go b/internal/framework/flex/auto_expand.go index c9cc9cd8aca..988623c3be7 100644 --- a/internal/framework/flex/auto_expand.go +++ b/internal/framework/flex/auto_expand.go @@ -380,7 +380,7 @@ func (expander autoExpander) list(ctx context.Context, vFrom basetypes.ListValua switch v.ElementType(ctx).(type) { case basetypes.Int64Typable: - diags.Append(expander.listOfInt64(ctx, v, vTo)...) + diags.Append(expander.listOrSetOfInt64(ctx, v, vTo)...) return diags case basetypes.StringTypable: @@ -402,8 +402,8 @@ func (expander autoExpander) list(ctx context.Context, vFrom basetypes.ListValua return diags } -// listOfString copies a Plugin Framework ListOfInt64(ish) value to a compatible AWS API value. -func (expander autoExpander) listOfInt64(ctx context.Context, vFrom basetypes.ListValue, vTo reflect.Value) diag.Diagnostics { +// listOrSetOfInt64 copies a Plugin Framework ListOfInt64(ish) or SetOfInt64(ish) value to a compatible AWS API value. +func (expander autoExpander) listOrSetOfInt64(ctx context.Context, vFrom listOrSetValue, vTo reflect.Value) diag.Diagnostics { var diags diag.Diagnostics switch vTo.Kind() { @@ -644,8 +644,7 @@ func (expander autoExpander) set(ctx context.Context, vFrom basetypes.SetValuabl switch v.ElementType(ctx).(type) { case basetypes.Int64Typable: - // TODO - // diags.Append(expander.setOfInt64(ctx, v, vTo)...) + diags.Append(expander.listOrSetOfInt64(ctx, v, vTo)...) return diags case basetypes.StringTypable: diff --git a/internal/framework/flex/auto_expand_test.go b/internal/framework/flex/auto_expand_test.go index fd6e037d358..8e70d7bda4b 100644 --- a/internal/framework/flex/auto_expand_test.go +++ b/internal/framework/flex/auto_expand_test.go @@ -872,6 +872,99 @@ func TestExpandListOfInt64(t *testing.T) { runAutoExpandTestCases(ctx, t, testCases) } +func TestExpandSetOfInt64(t *testing.T) { + t.Parallel() + + ctx := context.Background() + testCases := autoFlexTestCases{ + { + TestName: "valid value []int64", + Source: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]int64{}, + WantTarget: &[]int64{1, -1}, + }, + { + TestName: "empty value []int64", + Source: types.SetValueMust(types.Int64Type, []attr.Value{}), + Target: &[]int64{}, + WantTarget: &[]int64{}, + }, + { + TestName: "null value []int64", + Source: types.SetNull(types.Int64Type), + Target: &[]int64{}, + WantTarget: &[]int64{}, + }, + { + TestName: "valid value []*int64", + Source: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]*int64{}, + WantTarget: &[]*int64{aws.Int64(1), aws.Int64(-1)}, + }, + { + TestName: "empty value []*int64", + Source: types.SetValueMust(types.Int64Type, []attr.Value{}), + Target: &[]*int64{}, + WantTarget: &[]*int64{}, + }, + { + TestName: "null value []*int64", + Source: types.SetNull(types.Int64Type), + Target: &[]*int64{}, + WantTarget: &[]*int64{}, + }, + { + TestName: "valid value []int32", + Source: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]int32{}, + WantTarget: &[]int32{1, -1}, + }, + { + TestName: "empty value []int32", + Source: types.SetValueMust(types.Int64Type, []attr.Value{}), + Target: &[]int32{}, + WantTarget: &[]int32{}, + }, + { + TestName: "null value []int32", + Source: types.SetNull(types.Int64Type), + Target: &[]int32{}, + WantTarget: &[]int32{}, + }, + { + TestName: "valid value []*int32", + Source: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + Target: &[]*int32{}, + WantTarget: &[]*int32{aws.Int32(1), aws.Int32(-1)}, + }, + { + TestName: "empty value []*int32", + Source: types.SetValueMust(types.Int64Type, []attr.Value{}), + Target: &[]*int32{}, + WantTarget: &[]*int32{}, + }, + { + TestName: "null value []*int32", + Source: types.SetNull(types.Int64Type), + Target: &[]*int32{}, + WantTarget: &[]*int32{}, + }, + } + runAutoExpandTestCases(ctx, t, testCases) +} + func TestExpandListOfStringEnum(t *testing.T) { t.Parallel() diff --git a/internal/framework/flex/autoflex.go b/internal/framework/flex/autoflex.go index 136dfc48b8d..5905850bb3c 100644 --- a/internal/framework/flex/autoflex.go +++ b/internal/framework/flex/autoflex.go @@ -10,6 +10,7 @@ import ( "strings" pluralize "github.com/gertd/go-pluralize" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" ) @@ -221,3 +222,11 @@ func fieldExistsInStruct(field string, str reflect.Value) bool { return false } + +// listOrSetValue extends the Value interface for values that have ElementsAs and ElementType methods. +type listOrSetValue interface { + attr.Value + + ElementsAs(context.Context, any, bool) diag.Diagnostics + ElementType(context.Context) attr.Type +} From d8e20430651094bfde14b1686a0f0d44ce650ee0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 14:35:20 -0400 Subject: [PATCH 33/68] AutoFlEx: 'listOfString' -> 'listOrSetOfString'. --- internal/framework/flex/auto_expand.go | 70 ++++---------------------- internal/framework/flex/autoflex.go | 5 +- 2 files changed, 11 insertions(+), 64 deletions(-) diff --git a/internal/framework/flex/auto_expand.go b/internal/framework/flex/auto_expand.go index 988623c3be7..3b0987aa876 100644 --- a/internal/framework/flex/auto_expand.go +++ b/internal/framework/flex/auto_expand.go @@ -384,7 +384,7 @@ func (expander autoExpander) list(ctx context.Context, vFrom basetypes.ListValua return diags case basetypes.StringTypable: - diags.Append(expander.listOfString(ctx, v, vTo)...) + diags.Append(expander.listOrSetOfString(ctx, v, vTo)...) return diags case basetypes.ObjectTypable: @@ -403,7 +403,7 @@ func (expander autoExpander) list(ctx context.Context, vFrom basetypes.ListValua } // listOrSetOfInt64 copies a Plugin Framework ListOfInt64(ish) or SetOfInt64(ish) value to a compatible AWS API value. -func (expander autoExpander) listOrSetOfInt64(ctx context.Context, vFrom listOrSetValue, vTo reflect.Value) diag.Diagnostics { +func (expander autoExpander) listOrSetOfInt64(ctx context.Context, vFrom valueWithElementsAs, vTo reflect.Value) diag.Diagnostics { var diags diag.Diagnostics switch vTo.Kind() { @@ -458,15 +458,15 @@ func (expander autoExpander) listOrSetOfInt64(ctx context.Context, vFrom listOrS } tflog.Info(ctx, "AutoFlex Expand; incompatible types", map[string]interface{}{ - "from list[%s]": vFrom.ElementType(ctx), - "to": vTo.Kind(), + "from": vFrom.Type(ctx), + "to": vTo.Kind(), }) return diags } -// listOfString copies a Plugin Framework ListOfString(ish) value to a compatible AWS API value. -func (expander autoExpander) listOfString(ctx context.Context, vFrom basetypes.ListValue, vTo reflect.Value) diag.Diagnostics { +// listOrSetOfString copies a Plugin Framework ListOfString(ish) or SetOfString(ish) value to a compatible AWS API value. +func (expander autoExpander) listOrSetOfString(ctx context.Context, vFrom valueWithElementsAs, vTo reflect.Value) diag.Diagnostics { var diags diag.Diagnostics switch vTo.Kind() { @@ -510,8 +510,8 @@ func (expander autoExpander) listOfString(ctx context.Context, vFrom basetypes.L } tflog.Info(ctx, "AutoFlex Expand; incompatible types", map[string]interface{}{ - "from list[%s]": vFrom.ElementType(ctx), - "to": vTo.Kind(), + "from": vFrom.Type(ctx), + "to": vTo.Kind(), }) return diags @@ -648,7 +648,7 @@ func (expander autoExpander) set(ctx context.Context, vFrom basetypes.SetValuabl return diags case basetypes.StringTypable: - diags.Append(expander.setOfString(ctx, v, vTo)...) + diags.Append(expander.listOrSetOfString(ctx, v, vTo)...) return diags case basetypes.ObjectTypable: @@ -666,58 +666,6 @@ func (expander autoExpander) set(ctx context.Context, vFrom basetypes.SetValuabl return diags } -// setOfString copies a Plugin Framework SetOfString(ish) value to a compatible AWS API value. -func (expander autoExpander) setOfString(ctx context.Context, vFrom basetypes.SetValue, vTo reflect.Value) diag.Diagnostics { - var diags diag.Diagnostics - - switch vTo.Kind() { - case reflect.Slice: - switch tSliceElem := vTo.Type().Elem(); tSliceElem.Kind() { - case reflect.String: - // - // types.Set(OfString) -> []string. - // - var to []string - diags.Append(vFrom.ElementsAs(ctx, &to, false)...) - if diags.HasError() { - return diags - } - - // Copy elements individually to enable expansion of lists of - // custom string types (AWS enums) - vals := reflect.MakeSlice(vTo.Type(), len(to), len(to)) - for i := 0; i < len(to); i++ { - vals.Index(i).SetString(to[i]) - } - vTo.Set(vals) - return diags - - case reflect.Ptr: - switch tSliceElem.Elem().Kind() { - case reflect.String: - // - // types.Set(OfString) -> []*string. - // - var to []*string - diags.Append(vFrom.ElementsAs(ctx, &to, false)...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - } - } - - tflog.Info(ctx, "AutoFlex Expand; incompatible types", map[string]interface{}{ - "from set[%s]": vFrom.ElementType(ctx), - "to": vTo.Kind(), - }) - - return diags -} - // nestedObjectCollection copies a Plugin Framework NestedObjectCollectionValue value to a compatible AWS API value. func (expander autoExpander) nestedObjectCollection(ctx context.Context, vFrom fwtypes.NestedObjectCollectionValue, vTo reflect.Value) diag.Diagnostics { var diags diag.Diagnostics diff --git a/internal/framework/flex/autoflex.go b/internal/framework/flex/autoflex.go index 5905850bb3c..e2d0af61637 100644 --- a/internal/framework/flex/autoflex.go +++ b/internal/framework/flex/autoflex.go @@ -223,10 +223,9 @@ func fieldExistsInStruct(field string, str reflect.Value) bool { return false } -// listOrSetValue extends the Value interface for values that have ElementsAs and ElementType methods. -type listOrSetValue interface { +// valueWithElementsAs extends the Value interface for values that have an ElementsAs method. +type valueWithElementsAs interface { attr.Value ElementsAs(context.Context, any, bool) diag.Diagnostics - ElementType(context.Context) attr.Type } From 218107dd0e0e9deb24d1adebf9e8a33945bdfb1b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 15:26:59 -0400 Subject: [PATCH 34/68] Add 'flex.ExpandFrameworkInt64List' and 'flex.ExpandFrameworkInt64ValueList'. --- internal/framework/flex/list.go | 16 +++++ internal/framework/flex/list_test.go | 98 ++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/internal/framework/flex/list.go b/internal/framework/flex/list.go index 602cf311c00..f01a724deae 100644 --- a/internal/framework/flex/list.go +++ b/internal/framework/flex/list.go @@ -13,6 +13,22 @@ import ( fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" ) +func ExpandFrameworkInt64List(ctx context.Context, v basetypes.ListValuable) []*int64 { + var output []*int64 + + must(Expand(ctx, v, &output)) + + return output +} + +func ExpandFrameworkInt64ValueList(ctx context.Context, v basetypes.ListValuable) []int64 { + var output []int64 + + must(Expand(ctx, v, &output)) + + return output +} + func ExpandFrameworkStringList(ctx context.Context, v basetypes.ListValuable) []*string { var output []*string diff --git a/internal/framework/flex/list_test.go b/internal/framework/flex/list_test.go index 80ccd430e4c..91e39bb84e1 100644 --- a/internal/framework/flex/list_test.go +++ b/internal/framework/flex/list_test.go @@ -14,6 +14,104 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" ) +func TestExpandFrameworkInt64List(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.List + expected []*int64 + } + tests := map[string]testCase{ + "null": { + input: types.ListNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.ListUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []*int64{aws.Int64(1), aws.Int64(-1)}, + }, + "zero elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{}), + expected: []*int64{}, + }, + "invalid element type": { + input: types.ListValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt64List(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestExpandFrameworkInt64ValueList(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.List + expected []int64 + } + tests := map[string]testCase{ + "null": { + input: types.ListNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.ListUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []int64{1, -1}, + }, + "zero elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{}), + expected: []int64{}, + }, + "invalid element type": { + input: types.ListValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt64ValueList(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestExpandFrameworkStringList(t *testing.T) { t.Parallel() From b3d004db033f37f16c12d318dc1d12b2b458f238 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 15:30:00 -0400 Subject: [PATCH 35/68] Add 'flex.ExpandFrameworkInt32List' and 'flex.ExpandFrameworkInt32ValueList'. --- internal/framework/flex/list.go | 16 +++++ internal/framework/flex/list_test.go | 98 ++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/internal/framework/flex/list.go b/internal/framework/flex/list.go index f01a724deae..5687d44c20f 100644 --- a/internal/framework/flex/list.go +++ b/internal/framework/flex/list.go @@ -13,6 +13,22 @@ import ( fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" ) +func ExpandFrameworkInt32List(ctx context.Context, v basetypes.ListValuable) []*int32 { + var output []*int32 + + must(Expand(ctx, v, &output)) + + return output +} + +func ExpandFrameworkInt32ValueList(ctx context.Context, v basetypes.ListValuable) []int32 { + var output []int32 + + must(Expand(ctx, v, &output)) + + return output +} + func ExpandFrameworkInt64List(ctx context.Context, v basetypes.ListValuable) []*int64 { var output []*int64 diff --git a/internal/framework/flex/list_test.go b/internal/framework/flex/list_test.go index 91e39bb84e1..8ac99cc71d9 100644 --- a/internal/framework/flex/list_test.go +++ b/internal/framework/flex/list_test.go @@ -14,6 +14,104 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" ) +func TestExpandFrameworkInt32List(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.List + expected []*int32 + } + tests := map[string]testCase{ + "null": { + input: types.ListNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.ListUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []*int32{aws.Int32(1), aws.Int32(-1)}, + }, + "zero elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{}), + expected: []*int32{}, + }, + "invalid element type": { + input: types.ListValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt32List(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestExpandFrameworkInt32ValueList(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.List + expected []int32 + } + tests := map[string]testCase{ + "null": { + input: types.ListNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.ListUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []int32{1, -1}, + }, + "zero elements": { + input: types.ListValueMust(types.Int64Type, []attr.Value{}), + expected: []int32{}, + }, + "invalid element type": { + input: types.ListValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt32ValueList(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestExpandFrameworkInt64List(t *testing.T) { t.Parallel() From defab6a4032985ce5b5a0626d146847d68b04f0b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 15:33:04 -0400 Subject: [PATCH 36/68] Add 'flex.ExpandFrameworkInt64Set' and 'flex.ExpandFrameworkInt64ValueSet'. --- internal/framework/flex/set.go | 16 +++++ internal/framework/flex/set_test.go | 98 +++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/internal/framework/flex/set.go b/internal/framework/flex/set.go index 08b55107ba2..4bd15d8dc7e 100644 --- a/internal/framework/flex/set.go +++ b/internal/framework/flex/set.go @@ -13,6 +13,22 @@ import ( itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) +func ExpandFrameworkInt64Set(ctx context.Context, v basetypes.SetValuable) []*int64 { + var output []*int64 + + must(Expand(ctx, v, &output)) + + return output +} + +func ExpandFrameworkInt64ValueSet(ctx context.Context, v basetypes.SetValuable) []int64 { + var output []int64 + + must(Expand(ctx, v, &output)) + + return output +} + func ExpandFrameworkStringSet(ctx context.Context, v basetypes.SetValuable) []*string { var output []*string diff --git a/internal/framework/flex/set_test.go b/internal/framework/flex/set_test.go index 74afc03eb14..921e283eb34 100644 --- a/internal/framework/flex/set_test.go +++ b/internal/framework/flex/set_test.go @@ -15,6 +15,104 @@ import ( itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) +func TestExpandFrameworkInt64Set(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.Set + expected []*int64 + } + tests := map[string]testCase{ + "null": { + input: types.SetNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.SetUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []*int64{aws.Int64(1), aws.Int64(-1)}, + }, + "zero elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{}), + expected: []*int64{}, + }, + "invalid element type": { + input: types.SetValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt64Set(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestExpandFrameworkInt64ValueSet(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.Set + expected []int64 + } + tests := map[string]testCase{ + "null": { + input: types.SetNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.SetUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []int64{1, -1}, + }, + "zero elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{}), + expected: []int64{}, + }, + "invalid element type": { + input: types.SetValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt64ValueSet(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestExpandFrameworkStringSet(t *testing.T) { t.Parallel() From 733a7f4af54a32ead425ba79d2c42e4ef12d239c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 15:35:45 -0400 Subject: [PATCH 37/68] Add 'flex.ExpandFrameworkInt32Set' and 'flex.ExpandFrameworkInt32ValueSet'. --- internal/framework/flex/set.go | 16 +++++ internal/framework/flex/set_test.go | 98 +++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/internal/framework/flex/set.go b/internal/framework/flex/set.go index 4bd15d8dc7e..175ca17cd6d 100644 --- a/internal/framework/flex/set.go +++ b/internal/framework/flex/set.go @@ -13,6 +13,22 @@ import ( itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) +func ExpandFrameworkInt32Set(ctx context.Context, v basetypes.SetValuable) []*int32 { + var output []*int32 + + must(Expand(ctx, v, &output)) + + return output +} + +func ExpandFrameworkInt32ValueSet(ctx context.Context, v basetypes.SetValuable) []int32 { + var output []int32 + + must(Expand(ctx, v, &output)) + + return output +} + func ExpandFrameworkInt64Set(ctx context.Context, v basetypes.SetValuable) []*int64 { var output []*int64 diff --git a/internal/framework/flex/set_test.go b/internal/framework/flex/set_test.go index 921e283eb34..8179d41b259 100644 --- a/internal/framework/flex/set_test.go +++ b/internal/framework/flex/set_test.go @@ -15,6 +15,104 @@ import ( itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) +func TestExpandFrameworkInt32Set(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.Set + expected []*int32 + } + tests := map[string]testCase{ + "null": { + input: types.SetNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.SetUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []*int32{aws.Int32(1), aws.Int32(-1)}, + }, + "zero elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{}), + expected: []*int32{}, + }, + "invalid element type": { + input: types.SetValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt32Set(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestExpandFrameworkInt32ValueSet(t *testing.T) { + t.Parallel() + + type testCase struct { + input types.Set + expected []int32 + } + tests := map[string]testCase{ + "null": { + input: types.SetNull(types.Int64Type), + expected: nil, + }, + "unknown": { + input: types.SetUnknown(types.Int64Type), + expected: nil, + }, + "two elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + expected: []int32{1, -1}, + }, + "zero elements": { + input: types.SetValueMust(types.Int64Type, []attr.Value{}), + expected: []int32{}, + }, + "invalid element type": { + input: types.SetValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + }), + expected: nil, + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.ExpandFrameworkInt32ValueSet(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestExpandFrameworkInt64Set(t *testing.T) { t.Parallel() From dce1c1cd484c1bdd95bbf071fe2dd681c52b6c55 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 15:51:41 -0400 Subject: [PATCH 38/68] Add 'flex.FlattenFrameworkInt64List' and 'flex.FlattenFrameworkInt64ValueList'. --- internal/framework/flex/auto_flatten.go | 146 +++++++++++++++++++++++- internal/framework/flex/list.go | 32 ++++++ internal/framework/flex/list_test.go | 78 +++++++++++++ 3 files changed, 255 insertions(+), 1 deletion(-) diff --git a/internal/framework/flex/auto_flatten.go b/internal/framework/flex/auto_flatten.go index a4816e19963..bf14ec0c556 100644 --- a/internal/framework/flex/auto_flatten.go +++ b/internal/framework/flex/auto_flatten.go @@ -398,6 +398,77 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t var diags diag.Diagnostics switch tSliceElem := vFrom.Type().Elem(); tSliceElem.Kind() { + case reflect.Int64: + switch tTo := tTo.(type) { + case basetypes.ListTypable: + // + // []int64 -> types.List(OfInt64). + // + if vFrom.IsNil() { + to, d := tTo.ValueFromList(ctx, types.ListNull(types.Int64Type)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + elements := make([]attr.Value, vFrom.Len()) + for i := 0; i < vFrom.Len(); i++ { + elements[i] = types.Int64Value(vFrom.Index(i).Int()) + } + list, d := types.ListValue(types.Int64Type, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromList(ctx, list) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + + case basetypes.SetTypable: + // + // []int64 -> types.Set(OfInt64). + // + if vFrom.IsNil() { + to, d := tTo.ValueFromSet(ctx, types.SetNull(types.Int64Type)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + elements := make([]attr.Value, vFrom.Len()) + for i := 0; i < vFrom.Len(); i++ { + elements[i] = types.Int64Value(vFrom.Index(i).Int()) + } + set, d := types.SetValue(types.Int64Type, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromSet(ctx, set) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + case reflect.String: switch tTo := tTo.(type) { case basetypes.ListTypable: @@ -471,6 +542,79 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t case reflect.Ptr: switch tSliceElem.Elem().Kind() { + case reflect.Int64: + switch tTo := tTo.(type) { + case basetypes.ListTypable: + // + // []*int64 -> types.List(OfInt64). + // + if vFrom.IsNil() { + to, d := tTo.ValueFromList(ctx, types.ListNull(types.Int64Type)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + from := vFrom.Interface().([]*int64) + elements := make([]attr.Value, len(from)) + for i, v := range from { + elements[i] = types.Int64PointerValue(v) + } + list, d := types.ListValue(types.Int64Type, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromList(ctx, list) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + + case basetypes.SetTypable: + // + // []*int64 -> types.Set(OfInt64). + // + if vFrom.IsNil() { + to, d := tTo.ValueFromSet(ctx, types.SetNull(types.Int64Type)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + from := vFrom.Interface().([]*int64) + elements := make([]attr.Value, len(from)) + for i, v := range from { + elements[i] = types.Int64PointerValue(v) + } + set, d := types.SetValue(types.Int64Type, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromSet(ctx, set) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + case reflect.String: switch tTo := tTo.(type) { case basetypes.ListTypable: @@ -510,7 +654,7 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t case basetypes.SetTypable: // - // []string -> types.Set(OfString). + // []*string -> types.Set(OfString). // if vFrom.IsNil() { to, d := tTo.ValueFromSet(ctx, types.SetNull(types.StringType)) diff --git a/internal/framework/flex/list.go b/internal/framework/flex/list.go index 5687d44c20f..a04a915657c 100644 --- a/internal/framework/flex/list.go +++ b/internal/framework/flex/list.go @@ -61,6 +61,38 @@ func ExpandFrameworkStringValueList(ctx context.Context, v basetypes.ListValuabl return output } +// FlattenFrameworkInt64List converts a slice of int64 pointers to a framework List value. +// +// A nil slice is converted to a null List. +// An empty slice is converted to a null List. +func FlattenFrameworkInt64List(ctx context.Context, v []*int64) types.List { + if len(v) == 0 { + return types.ListNull(types.Int64Type) + } + + var output types.List + + must(Flatten(ctx, v, &output)) + + return output +} + +// FlattenFrameworkInt64ValueList converts a slice of int64 values to a framework List value. +// +// A nil slice is converted to a null List. +// An empty slice is converted to a null List. +func FlattenFrameworkInt64ValueList[T ~int64](ctx context.Context, v []T) types.List { + if len(v) == 0 { + return types.ListNull(types.Int64Type) + } + + var output types.List + + must(Flatten(ctx, v, &output)) + + return output +} + // FlattenFrameworkStringList converts a slice of string pointers to a framework List value. // // A nil slice is converted to a null List. diff --git a/internal/framework/flex/list_test.go b/internal/framework/flex/list_test.go index 8ac99cc71d9..8a46a7620a4 100644 --- a/internal/framework/flex/list_test.go +++ b/internal/framework/flex/list_test.go @@ -308,6 +308,84 @@ func TestExpandFrameworkStringValueList(t *testing.T) { } } +func TestFlattenFrameworkInt64List(t *testing.T) { + t.Parallel() + + type testCase struct { + input []*int64 + expected types.List + } + tests := map[string]testCase{ + "two elements": { + input: []*int64{aws.Int64(1), aws.Int64(-1)}, + expected: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []*int64{}, + expected: types.ListNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.ListNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt64List(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestFlattenFrameworkInt64ValueList(t *testing.T) { + t.Parallel() + + type testCase struct { + input []int64 + expected types.List + } + tests := map[string]testCase{ + "two elements": { + input: []int64{1, -1}, + expected: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []int64{}, + expected: types.ListNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.ListNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt64ValueList(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestFlattenFrameworkStringList(t *testing.T) { t.Parallel() From b07c6ffeca8aa7ed74f826f80d6ed65b0f2ce72d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 15:57:23 -0400 Subject: [PATCH 39/68] Add 'flex.FlattenFrameworkInt64Set' and 'flex.FlattenFrameworkInt64ValueSet'. --- internal/framework/flex/set.go | 32 ++++++++ internal/framework/flex/set_test.go | 117 ++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/internal/framework/flex/set.go b/internal/framework/flex/set.go index 175ca17cd6d..84d58bacf66 100644 --- a/internal/framework/flex/set.go +++ b/internal/framework/flex/set.go @@ -61,6 +61,38 @@ func ExpandFrameworkStringValueSet(ctx context.Context, v basetypes.SetValuable) return output } +// FlattenFrameworkInt64Set converts a slice of int64 pointers to a framework Set value. +// +// A nil slice is converted to a null Set. +// An empty slice is converted to a null Set. +func FlattenFrameworkInt64Set(ctx context.Context, v []*int64) types.Set { + if len(v) == 0 { + return types.SetNull(types.Int64Type) + } + + var output types.Set + + must(Flatten(ctx, v, &output)) + + return output +} + +// FlattenFrameworkInt64ValueSet converts a slice of int64 values to a framework Set value. +// +// A nil slice is converted to a null Set. +// An empty slice is converted to a null Set. +func FlattenFrameworkInt64ValueSet[T ~int64](ctx context.Context, v []T) types.Set { + if len(v) == 0 { + return types.SetNull(types.Int64Type) + } + + var output types.Set + + must(Flatten(ctx, v, &output)) + + return output +} + // FlattenFrameworkStringSet converts a slice of string pointers to a framework Set value. // // A nil slice is converted to a null Set. diff --git a/internal/framework/flex/set_test.go b/internal/framework/flex/set_test.go index 8179d41b259..999fc39bf27 100644 --- a/internal/framework/flex/set_test.go +++ b/internal/framework/flex/set_test.go @@ -309,6 +309,123 @@ func TestExpandFrameworkStringValueSet(t *testing.T) { } } +func TestFlattenFrameworkInt64Set(t *testing.T) { + t.Parallel() + + type testCase struct { + input []*int64 + expected types.Set + } + tests := map[string]testCase{ + "two elements": { + input: []*int64{aws.Int64(1), aws.Int64(-1)}, + expected: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []*int64{}, + expected: types.SetNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.SetNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt64Set(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestFlattenFrameworkInt64ValueSet(t *testing.T) { + t.Parallel() + + type testCase struct { + input []int64 + expected types.Set + } + tests := map[string]testCase{ + "two elements": { + input: []int64{1, -1}, + expected: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []int64{}, + expected: types.SetNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.SetNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt64ValueSet(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestFlattenFrameworkStringSet(t *testing.T) { + t.Parallel() + + type testCase struct { + input []*string + expected types.Set + } + tests := map[string]testCase{ + "two elements": { + input: []*string{aws.String("GET"), aws.String("HEAD")}, + expected: types.SetValueMust(types.StringType, []attr.Value{ + types.StringValue("GET"), + types.StringValue("HEAD"), + }), + }, + "zero elements": { + input: []*string{}, + expected: types.SetNull(types.StringType), + }, + "nil array": { + input: nil, + expected: types.SetNull(types.StringType), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkStringSet(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestFlattenFrameworkStringValueSet(t *testing.T) { t.Parallel() From 2bf082a034126246d421f4b6c5b2c9df0fa02b50 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 16:08:22 -0400 Subject: [PATCH 40/68] Add 'flex.FlattenFrameworkInt32List' and 'flex.FlattenFrameworkInt32ValueList'. --- internal/framework/flex/auto_flatten.go | 83 ++++++++++++++++++++++++- internal/framework/flex/list.go | 32 ++++++++++ internal/framework/flex/list_test.go | 78 +++++++++++++++++++++++ 3 files changed, 192 insertions(+), 1 deletion(-) diff --git a/internal/framework/flex/auto_flatten.go b/internal/framework/flex/auto_flatten.go index bf14ec0c556..532de60feff 100644 --- a/internal/framework/flex/auto_flatten.go +++ b/internal/framework/flex/auto_flatten.go @@ -398,7 +398,7 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t var diags diag.Diagnostics switch tSliceElem := vFrom.Type().Elem(); tSliceElem.Kind() { - case reflect.Int64: + case reflect.Int32, reflect.Int64: switch tTo := tTo.(type) { case basetypes.ListTypable: // @@ -542,6 +542,79 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t case reflect.Ptr: switch tSliceElem.Elem().Kind() { + case reflect.Int32: + switch tTo := tTo.(type) { + case basetypes.ListTypable: + // + // []*int32 -> types.List(OfInt64). + // + if vFrom.IsNil() { + to, d := tTo.ValueFromList(ctx, types.ListNull(types.Int64Type)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + from := vFrom.Interface().([]*int32) + elements := make([]attr.Value, len(from)) + for i, v := range from { + elements[i] = newInt32PointerValue(v) + } + list, d := types.ListValue(types.Int64Type, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromList(ctx, list) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + + case basetypes.SetTypable: + // + // []*int32 -> types.Set(OfInt64). + // + if vFrom.IsNil() { + to, d := tTo.ValueFromSet(ctx, types.SetNull(types.Int64Type)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + from := vFrom.Interface().([]*int32) + elements := make([]attr.Value, len(from)) + for i, v := range from { + elements[i] = newInt32PointerValue(v) + } + set, d := types.SetValue(types.Int64Type, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromSet(ctx, set) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + case reflect.Int64: switch tTo := tTo.(type) { case basetypes.ListTypable: @@ -1127,3 +1200,11 @@ func blockKeyMapSet(to any, key reflect.Value) diag.Diagnostics { return diags } + +func newInt32PointerValue(value *int32) basetypes.Int64Value { + if value == nil { + return basetypes.NewInt64Null() + } + + return basetypes.NewInt64Value(int64(*value)) +} diff --git a/internal/framework/flex/list.go b/internal/framework/flex/list.go index a04a915657c..0c018caed90 100644 --- a/internal/framework/flex/list.go +++ b/internal/framework/flex/list.go @@ -61,6 +61,38 @@ func ExpandFrameworkStringValueList(ctx context.Context, v basetypes.ListValuabl return output } +// FlattenFrameworkInt64List converts a slice of int32 pointers to a framework List value. +// +// A nil slice is converted to a null List. +// An empty slice is converted to a null List. +func FlattenFrameworkInt32List(ctx context.Context, v []*int32) types.List { + if len(v) == 0 { + return types.ListNull(types.Int64Type) + } + + var output types.List + + must(Flatten(ctx, v, &output)) + + return output +} + +// FlattenFrameworkInt64ValueList converts a slice of int32 values to a framework List value. +// +// A nil slice is converted to a null List. +// An empty slice is converted to a null List. +func FlattenFrameworkInt32ValueList[T ~int32](ctx context.Context, v []T) types.List { + if len(v) == 0 { + return types.ListNull(types.Int64Type) + } + + var output types.List + + must(Flatten(ctx, v, &output)) + + return output +} + // FlattenFrameworkInt64List converts a slice of int64 pointers to a framework List value. // // A nil slice is converted to a null List. diff --git a/internal/framework/flex/list_test.go b/internal/framework/flex/list_test.go index 8a46a7620a4..5239e07269f 100644 --- a/internal/framework/flex/list_test.go +++ b/internal/framework/flex/list_test.go @@ -308,6 +308,84 @@ func TestExpandFrameworkStringValueList(t *testing.T) { } } +func TestFlattenFrameworkInt32List(t *testing.T) { + t.Parallel() + + type testCase struct { + input []*int32 + expected types.List + } + tests := map[string]testCase{ + "two elements": { + input: []*int32{aws.Int32(1), aws.Int32(-1)}, + expected: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []*int32{}, + expected: types.ListNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.ListNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt32List(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestFlattenFrameworkInt32ValueList(t *testing.T) { + t.Parallel() + + type testCase struct { + input []int32 + expected types.List + } + tests := map[string]testCase{ + "two elements": { + input: []int32{1, -1}, + expected: types.ListValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []int32{}, + expected: types.ListNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.ListNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt32ValueList(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestFlattenFrameworkInt64List(t *testing.T) { t.Parallel() From 8a4632878c3cd9a3e2e2d705a26d0600fd1f84f6 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 16:11:27 -0400 Subject: [PATCH 41/68] Add 'flex.FlattenFrameworkInt32Set' and 'flex.FlattenFrameworkInt32ValueSet'. --- internal/framework/flex/set.go | 32 ++++++++++++ internal/framework/flex/set_test.go | 78 +++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/internal/framework/flex/set.go b/internal/framework/flex/set.go index 84d58bacf66..df78d2ba8d4 100644 --- a/internal/framework/flex/set.go +++ b/internal/framework/flex/set.go @@ -61,6 +61,38 @@ func ExpandFrameworkStringValueSet(ctx context.Context, v basetypes.SetValuable) return output } +// FlattenFrameworkInt64Set converts a slice of int32 pointers to a framework Set value. +// +// A nil slice is converted to a null Set. +// An empty slice is converted to a null Set. +func FlattenFrameworkInt32Set(ctx context.Context, v []*int32) types.Set { + if len(v) == 0 { + return types.SetNull(types.Int64Type) + } + + var output types.Set + + must(Flatten(ctx, v, &output)) + + return output +} + +// FlattenFrameworkInt64ValueSet converts a slice of int32 values to a framework Set value. +// +// A nil slice is converted to a null Set. +// An empty slice is converted to a null Set. +func FlattenFrameworkInt32ValueSet[T ~int32](ctx context.Context, v []T) types.Set { + if len(v) == 0 { + return types.SetNull(types.Int64Type) + } + + var output types.Set + + must(Flatten(ctx, v, &output)) + + return output +} + // FlattenFrameworkInt64Set converts a slice of int64 pointers to a framework Set value. // // A nil slice is converted to a null Set. diff --git a/internal/framework/flex/set_test.go b/internal/framework/flex/set_test.go index 999fc39bf27..72e40088dd9 100644 --- a/internal/framework/flex/set_test.go +++ b/internal/framework/flex/set_test.go @@ -309,6 +309,84 @@ func TestExpandFrameworkStringValueSet(t *testing.T) { } } +func TestFlattenFrameworkInt32Set(t *testing.T) { + t.Parallel() + + type testCase struct { + input []*int32 + expected types.Set + } + tests := map[string]testCase{ + "two elements": { + input: []*int32{aws.Int32(1), aws.Int32(-1)}, + expected: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []*int32{}, + expected: types.SetNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.SetNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt32Set(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + +func TestFlattenFrameworkInt32ValueSet(t *testing.T) { + t.Parallel() + + type testCase struct { + input []int32 + expected types.Set + } + tests := map[string]testCase{ + "two elements": { + input: []int32{1, -1}, + expected: types.SetValueMust(types.Int64Type, []attr.Value{ + types.Int64Value(1), + types.Int64Value(-1), + }), + }, + "zero elements": { + input: []int32{}, + expected: types.SetNull(types.Int64Type), + }, + "nil array": { + input: nil, + expected: types.SetNull(types.Int64Type), + }, + } + + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := flex.FlattenFrameworkInt32ValueSet(context.Background(), test.input) + + if diff := cmp.Diff(got, test.expected); diff != "" { + t.Errorf("unexpected diff (+wanted, -got): %s", diff) + } + }) + } +} + func TestFlattenFrameworkInt64Set(t *testing.T) { t.Parallel() From 1528cc065d1ba9bec7823493ed47927cebd95f1b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 16:31:42 -0400 Subject: [PATCH 42/68] AutoFlEx: Add 'sliceToList' and 'sliceToSet'. --- internal/framework/flex/auto_flatten.go | 192 ++++++++++-------------- 1 file changed, 80 insertions(+), 112 deletions(-) diff --git a/internal/framework/flex/auto_flatten.go b/internal/framework/flex/auto_flatten.go index 532de60feff..f899afa737f 100644 --- a/internal/framework/flex/auto_flatten.go +++ b/internal/framework/flex/auto_flatten.go @@ -404,68 +404,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []int64 -> types.List(OfInt64). // - if vFrom.IsNil() { - to, d := tTo.ValueFromList(ctx, types.ListNull(types.Int64Type)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - elements := make([]attr.Value, vFrom.Len()) - for i := 0; i < vFrom.Len(); i++ { - elements[i] = types.Int64Value(vFrom.Index(i).Int()) - } - list, d := types.ListValue(types.Int64Type, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromList(ctx, list) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(flattener.sliceToList(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementValue)...) return diags case basetypes.SetTypable: // // []int64 -> types.Set(OfInt64). // - if vFrom.IsNil() { - to, d := tTo.ValueFromSet(ctx, types.SetNull(types.Int64Type)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - elements := make([]attr.Value, vFrom.Len()) - for i := 0; i < vFrom.Len(); i++ { - elements[i] = types.Int64Value(vFrom.Index(i).Int()) - } - set, d := types.SetValue(types.Int64Type, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromSet(ctx, set) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(flattener.sliceToSet(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementValue)...) return diags } @@ -475,68 +421,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []string -> types.List(OfString). // - if vFrom.IsNil() { - to, d := tTo.ValueFromList(ctx, types.ListNull(types.StringType)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - elements := make([]attr.Value, vFrom.Len()) - for i := 0; i < vFrom.Len(); i++ { - elements[i] = types.StringValue(vFrom.Index(i).String()) - } - list, d := types.ListValue(types.StringType, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromList(ctx, list) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(flattener.sliceToList(ctx, vFrom, tTo, vTo, types.StringType, newStringElementValue)...) return diags case basetypes.SetTypable: // // []string -> types.Set(OfString). // - if vFrom.IsNil() { - to, d := tTo.ValueFromSet(ctx, types.SetNull(types.StringType)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - elements := make([]attr.Value, vFrom.Len()) - for i := 0; i < vFrom.Len(); i++ { - elements[i] = types.StringValue(vFrom.Index(i).String()) - } - set, d := types.SetValue(types.StringType, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromSet(ctx, set) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(flattener.sliceToSet(ctx, vFrom, tTo, vTo, types.StringType, newStringElementValue)...) return diags } @@ -1201,6 +1093,82 @@ func blockKeyMapSet(to any, key reflect.Value) diag.Diagnostics { return diags } +func (flattener autoFlattener) sliceToList(ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTypable, vTo reflect.Value, elementType attr.Type, f func(reflect.Value) attr.Value) diag.Diagnostics { + var diags diag.Diagnostics + + if vFrom.IsNil() { + to, d := tTo.ValueFromList(ctx, types.ListNull(elementType)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + elements := make([]attr.Value, vFrom.Len()) + for i := 0; i < vFrom.Len(); i++ { + elements[i] = f(vFrom.Index(i)) + } + list, d := types.ListValue(elementType, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromList(ctx, list) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags +} + +func (flattener autoFlattener) sliceToSet(ctx context.Context, vFrom reflect.Value, tTo basetypes.SetTypable, vTo reflect.Value, elementType attr.Type, f func(reflect.Value) attr.Value) diag.Diagnostics { + var diags diag.Diagnostics + + if vFrom.IsNil() { + to, d := tTo.ValueFromSet(ctx, types.SetNull(elementType)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + elements := make([]attr.Value, vFrom.Len()) + for i := 0; i < vFrom.Len(); i++ { + elements[i] = f(vFrom.Index(i)) + } + list, d := types.SetValue(elementType, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromSet(ctx, list) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags +} + +func newInt64ElementValue(vElem reflect.Value) attr.Value { + return types.Int64Value(vElem.Int()) +} + +func newStringElementValue(vElem reflect.Value) attr.Value { + return types.StringValue(vElem.String()) +} + func newInt32PointerValue(value *int32) basetypes.Int64Value { if value == nil { return basetypes.NewInt64Null() From b3c159e9fe613280807d8c1f92974c4d6ddeabb9 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 16:57:41 -0400 Subject: [PATCH 43/68] AutoFlEx: Add 'sliceOfPtrToList' and 'sliceOfPtrToSet'. --- internal/framework/flex/auto_flatten.go | 284 +++++++++--------------- 1 file changed, 99 insertions(+), 185 deletions(-) diff --git a/internal/framework/flex/auto_flatten.go b/internal/framework/flex/auto_flatten.go index f899afa737f..1acea96cd97 100644 --- a/internal/framework/flex/auto_flatten.go +++ b/internal/framework/flex/auto_flatten.go @@ -404,14 +404,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []int64 -> types.List(OfInt64). // - diags.Append(flattener.sliceToList(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementValue)...) + diags.Append(sliceToList(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromReflectValue)...) return diags case basetypes.SetTypable: // // []int64 -> types.Set(OfInt64). // - diags.Append(flattener.sliceToSet(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementValue)...) + diags.Append(sliceToSet(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromReflectValue)...) return diags } @@ -421,14 +421,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []string -> types.List(OfString). // - diags.Append(flattener.sliceToList(ctx, vFrom, tTo, vTo, types.StringType, newStringElementValue)...) + diags.Append(sliceToList(ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromReflectValue)...) return diags case basetypes.SetTypable: // // []string -> types.Set(OfString). // - diags.Append(flattener.sliceToSet(ctx, vFrom, tTo, vTo, types.StringType, newStringElementValue)...) + diags.Append(sliceToSet(ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromReflectValue)...) return diags } @@ -440,70 +440,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []*int32 -> types.List(OfInt64). // - if vFrom.IsNil() { - to, d := tTo.ValueFromList(ctx, types.ListNull(types.Int64Type)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - from := vFrom.Interface().([]*int32) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = newInt32PointerValue(v) - } - list, d := types.ListValue(types.Int64Type, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromList(ctx, list) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(sliceOfPtrToList[[]*int32](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt32PtrValue)...) return diags case basetypes.SetTypable: // // []*int32 -> types.Set(OfInt64). // - if vFrom.IsNil() { - to, d := tTo.ValueFromSet(ctx, types.SetNull(types.Int64Type)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - from := vFrom.Interface().([]*int32) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = newInt32PointerValue(v) - } - set, d := types.SetValue(types.Int64Type, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromSet(ctx, set) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(sliceOfPtrToSet[[]*int32](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt32PtrValue)...) return diags } @@ -513,70 +457,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []*int64 -> types.List(OfInt64). // - if vFrom.IsNil() { - to, d := tTo.ValueFromList(ctx, types.ListNull(types.Int64Type)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - from := vFrom.Interface().([]*int64) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = types.Int64PointerValue(v) - } - list, d := types.ListValue(types.Int64Type, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromList(ctx, list) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(sliceOfPtrToList[[]*int64](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt64PtrValue)...) return diags case basetypes.SetTypable: // // []*int64 -> types.Set(OfInt64). // - if vFrom.IsNil() { - to, d := tTo.ValueFromSet(ctx, types.SetNull(types.Int64Type)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - from := vFrom.Interface().([]*int64) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = types.Int64PointerValue(v) - } - set, d := types.SetValue(types.Int64Type, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromSet(ctx, set) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(sliceOfPtrToSet[[]*int64](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt64PtrValue)...) return diags } @@ -586,70 +474,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []*string -> types.List(OfString). // - if vFrom.IsNil() { - to, d := tTo.ValueFromList(ctx, types.ListNull(types.StringType)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - from := vFrom.Interface().([]*string) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = types.StringPointerValue(v) - } - list, d := types.ListValue(types.StringType, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromList(ctx, list) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(sliceOfPtrToList[[]*string](ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromGoStringPtrValue)...) return diags case basetypes.SetTypable: // // []*string -> types.Set(OfString). // - if vFrom.IsNil() { - to, d := tTo.ValueFromSet(ctx, types.SetNull(types.StringType)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags - } - - from := vFrom.Interface().([]*string) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = types.StringPointerValue(v) - } - set, d := types.SetValue(types.StringType, elements) - diags.Append(d...) - if diags.HasError() { - return diags - } - - to, d := tTo.ValueFromSet(ctx, set) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) + diags.Append(sliceOfPtrToSet[[]*string](ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromGoStringPtrValue)...) return diags } @@ -1093,7 +925,7 @@ func blockKeyMapSet(to any, key reflect.Value) diag.Diagnostics { return diags } -func (flattener autoFlattener) sliceToList(ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTypable, vTo reflect.Value, elementType attr.Type, f func(reflect.Value) attr.Value) diag.Diagnostics { +func sliceToList(ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTypable, vTo reflect.Value, elementType attr.Type, f elementFromReflectValueFunc) diag.Diagnostics { var diags diag.Diagnostics if vFrom.IsNil() { @@ -1127,7 +959,42 @@ func (flattener autoFlattener) sliceToList(ctx context.Context, vFrom reflect.Va return diags } -func (flattener autoFlattener) sliceToSet(ctx context.Context, vFrom reflect.Value, tTo basetypes.SetTypable, vTo reflect.Value, elementType attr.Type, f func(reflect.Value) attr.Value) diag.Diagnostics { +func sliceOfPtrToList[S []E, E any](ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTypable, vTo reflect.Value, elementType attr.Type, f elementFromGoValueFunc[E]) diag.Diagnostics { + var diags diag.Diagnostics + + if vFrom.IsNil() { + to, d := tTo.ValueFromList(ctx, types.ListNull(elementType)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + from := vFrom.Interface().(S) + elements := make([]attr.Value, len(from)) + for i, v := range from { + elements[i] = f(v) + } + list, d := types.ListValue(elementType, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromList(ctx, list) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags +} + +func sliceToSet(ctx context.Context, vFrom reflect.Value, tTo basetypes.SetTypable, vTo reflect.Value, elementType attr.Type, f elementFromReflectValueFunc) diag.Diagnostics { var diags diag.Diagnostics if vFrom.IsNil() { @@ -1145,13 +1012,13 @@ func (flattener autoFlattener) sliceToSet(ctx context.Context, vFrom reflect.Val for i := 0; i < vFrom.Len(); i++ { elements[i] = f(vFrom.Index(i)) } - list, d := types.SetValue(elementType, elements) + set, d := types.SetValue(elementType, elements) diags.Append(d...) if diags.HasError() { return diags } - to, d := tTo.ValueFromSet(ctx, list) + to, d := tTo.ValueFromSet(ctx, set) diags.Append(d...) if diags.HasError() { return diags @@ -1161,18 +1028,65 @@ func (flattener autoFlattener) sliceToSet(ctx context.Context, vFrom reflect.Val return diags } -func newInt64ElementValue(vElem reflect.Value) attr.Value { +func sliceOfPtrToSet[S []E, E any](ctx context.Context, vFrom reflect.Value, tTo basetypes.SetTypable, vTo reflect.Value, elementType attr.Type, f elementFromGoValueFunc[E]) diag.Diagnostics { + var diags diag.Diagnostics + + if vFrom.IsNil() { + to, d := tTo.ValueFromSet(ctx, types.SetNull(elementType)) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags + } + + from := vFrom.Interface().(S) + elements := make([]attr.Value, len(from)) + for i, v := range from { + elements[i] = f(v) + } + set, d := types.SetValue(elementType, elements) + diags.Append(d...) + if diags.HasError() { + return diags + } + + to, d := tTo.ValueFromSet(ctx, set) + diags.Append(d...) + if diags.HasError() { + return diags + } + + vTo.Set(reflect.ValueOf(to)) + return diags +} + +type elementFromReflectValueFunc func(reflect.Value) attr.Value + +func newInt64ElementFromReflectValue(vElem reflect.Value) attr.Value { return types.Int64Value(vElem.Int()) } -func newStringElementValue(vElem reflect.Value) attr.Value { +func newStringElementFromReflectValue(vElem reflect.Value) attr.Value { return types.StringValue(vElem.String()) } -func newInt32PointerValue(value *int32) basetypes.Int64Value { +type elementFromGoValueFunc[T any] func(T) attr.Value + +func newInt64ElementFromGoInt32PtrValue(value *int32) attr.Value { if value == nil { return basetypes.NewInt64Null() } return basetypes.NewInt64Value(int64(*value)) } + +func newInt64ElementFromGoInt64PtrValue(value *int64) attr.Value { + return basetypes.NewInt64PointerValue(value) +} + +func newStringElementFromGoStringPtrValue(value *string) attr.Value { + return basetypes.NewStringPointerValue(value) +} From a026773c7e833fd3ab38a00842f195e6270d0149 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Wed, 19 Jun 2024 18:19:08 -0400 Subject: [PATCH 44/68] r/aws_networkfirewall_tls_inspection_configuration: Fixes after some initial testing. --- internal/framework/types/setof.go | 1 - .../tls_inspection_configuration.go | 84 ++++++++++--------- ...tls_inspection_configuration.html.markdown | 2 +- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/internal/framework/types/setof.go b/internal/framework/types/setof.go index 8588aab42e5..357f1f63f8b 100644 --- a/internal/framework/types/setof.go +++ b/internal/framework/types/setof.go @@ -25,7 +25,6 @@ type setTypeOf[T attr.Value] struct { } var ( - SetOfInt64Type = setTypeOf[basetypes.Int64Value]{basetypes.SetType{ElemType: basetypes.Int64Type{}}} SetOfStringType = setTypeOf[basetypes.StringValue]{basetypes.SetType{ElemType: basetypes.StringType{}}} ) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index e5c4953374d..365c7d74c96 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -14,14 +14,16 @@ import ( "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/resourcevalidator" "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" @@ -82,6 +84,20 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request stringvalidator.LengthBetween(1, 512), }, }, + names.AttrEncryptionConfiguration: schema.ListAttribute{ + CustomType: fwtypes.NewListNestedObjectTypeOf[encryptionConfigurationModel](ctx), + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.List{ + listplanmodifier.UseStateForUnknown(), + }, + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + }, + ElementType: types.ObjectType{ + AttrTypes: fwtypes.AttributeTypesMust[encryptionConfigurationModel](ctx), + }, + }, names.AttrID: framework.IDAttribute(), names.AttrName: schema.StringAttribute{ Required: true, @@ -90,7 +106,7 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, Validators: []validator.String{ stringvalidator.LengthBetween(1, 128), - stringvalidator.RegexMatches(regexache.MustCompile(`^[a-zA-Z0-9-]+$`), "Must contain only alphanumeric characters and dash '-'"), + stringvalidator.RegexMatches(regexache.MustCompile(`^[a-zA-Z0-9-]+$`), "Must contain only a-z, A-Z, 0-9 and - (hyphen)"), }, }, "number_of_associations": schema.Int64Attribute{ @@ -107,29 +123,6 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, }, Blocks: map[string]schema.Block{ - names.AttrEncryptionConfiguration: schema.ListNestedBlock{ - CustomType: fwtypes.NewListNestedObjectTypeOf[encryptionConfigurationModel](ctx), - Validators: []validator.List{ - listvalidator.SizeAtMost(1), - }, - NestedObject: schema.NestedBlockObject{ - Attributes: map[string]schema.Attribute{ - names.AttrKeyID: schema.StringAttribute{ - CustomType: fwtypes.ARNType, - Optional: true, - Computed: true, - }, - names.AttrType: schema.StringAttribute{ - Optional: true, - Computed: true, - Default: stringdefault.StaticString(networkfirewall.EncryptionTypeAwsOwnedKmsKey), - Validators: []validator.String{ - stringvalidator.OneOf(networkfirewall.EncryptionType_Values()...), - }, - }, - }, - }, - }, names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{ Create: true, Update: true, @@ -139,12 +132,16 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request CustomType: fwtypes.NewListNestedObjectTypeOf[tlsInspectionConfigurationModel](ctx), Validators: []validator.List{ listvalidator.IsRequired(), - listvalidator.SizeBetween(1, 1), + listvalidator.SizeAtMost(1), }, NestedObject: schema.NestedBlockObject{ Blocks: map[string]schema.Block{ "server_certificate_configuration": schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[serverCertificateConfigurationModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + listvalidator.SizeAtMost(1), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "certificate_authority_arn": schema.StringAttribute{ @@ -177,10 +174,13 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, names.AttrScope: schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[serverCertificateScopeModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "protocols": schema.SetAttribute{ - CustomType: fwtypes.SetOfInt64Type, + CustomType: fwtypes.NewSetTypeOf[types.Int64](ctx), ElementType: types.Int64Type, Required: true, Validators: []validator.Set{ @@ -210,6 +210,9 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, names.AttrDestination: schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[addressModel](ctx), + Validators: []validator.List{ + listvalidator.IsRequired(), + }, NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "address_definition": schema.StringAttribute{ @@ -241,7 +244,7 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, }, }, - "sources": schema.ListNestedBlock{ + "source": schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[addressModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ @@ -451,6 +454,15 @@ func (r *tlsInspectionConfigurationResource) Delete(ctx context.Context, request } } +func (r *tlsInspectionConfigurationResource) ConfigValidators(context.Context) []resource.ConfigValidator { + return []resource.ConfigValidator{ + resourcevalidator.AtLeastOneOf( + path.MatchRoot("tls_inspection_configuration").AtListIndex(0).AtName("server_certificate_configuration").AtListIndex(0).AtName("certificate_authority_arn"), + path.MatchRoot("tls_inspection_configuration").AtListIndex(0).AtName("server_certificate_configuration").AtListIndex(0).AtName("server_certificate"), + ), + } +} + func findTLSInspectionConfigurationByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { input := &networkfirewall.DescribeTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(arn), @@ -576,25 +588,17 @@ func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfir func flattenDescribeTLSInspectionConfigurationOutput(ctx context.Context, data *tlsInspectionConfigurationResourceModel, apiObject *networkfirewall.DescribeTLSInspectionConfigurationOutput) diag.Diagnostics { var diags diag.Diagnostics - d := fwflex.Flatten(ctx, apiObject.TLSInspectionConfigurationResponse, &data) - diags.Append(d...) - if diags.HasError() { - return diags - } - - var tlsInspectionConfigurationData tlsInspectionConfigurationModel - d = fwflex.Flatten(ctx, apiObject.TLSInspectionConfiguration, &tlsInspectionConfigurationData) + d := fwflex.Flatten(ctx, apiObject.TLSInspectionConfigurationResponse, data) diags.Append(d...) if diags.HasError() { return diags } - tlsInspectionConfiguration, d := fwtypes.NewListNestedObjectValueOfPtr(ctx, &tlsInspectionConfigurationData) + d = fwflex.Flatten(ctx, apiObject.TLSInspectionConfiguration, &data.TLSInspectionConfiguration) diags.Append(d...) if diags.HasError() { return diags } - data.TLSInspectionConfiguration = tlsInspectionConfiguration return diags } @@ -627,7 +631,7 @@ func (model *tlsInspectionConfigurationResourceModel) setID() { } type encryptionConfigurationModel struct { - KeyID fwtypes.ARN `tfsdk:"key_id"` + KeyID types.String `tfsdk:"key_id"` Type types.String `tfsdk:"type"` } @@ -638,7 +642,7 @@ type tlsInspectionConfigurationModel struct { type serverCertificateConfigurationModel struct { CertificateAuthorityARN fwtypes.ARN `tfsdk:"certificate_authority_arn"` CheckCertificateRevocationsStatus fwtypes.ListNestedObjectValueOf[checkCertificateRevocationStatusActionsModel] `tfsdk:"check_certificate_revocation_status"` - Scope fwtypes.ListNestedObjectValueOf[serverCertificateScopeModel] `tfsdk:"scope"` + Scopes fwtypes.ListNestedObjectValueOf[serverCertificateScopeModel] `tfsdk:"scope"` ServerCertificates fwtypes.ListNestedObjectValueOf[serverCertificateModel] `tfsdk:"server_certificate"` } diff --git a/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown index 0e071179a9f..170291d1413 100644 --- a/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown +++ b/website/docs/r/networkfirewall_tls_inspection_configuration.html.markdown @@ -261,7 +261,7 @@ The `check_certificate_revocation_status` block supports the following arguments The `scope` block supports the following arguments: -* `destination` - (Optional) Set of configuration blocks describing the destination IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any destination address. See [Destination](#destination) below for details. +* `destination` - (Required) Set of configuration blocks describing the destination IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any destination address. See [Destination](#destination) below for details. * `destination_ports` - (Optional) Set of configuration blocks describing the destination ports to inspect for. If not specified, this matches with any destination port. See [Destination Ports](#destination-ports) below for details. * `protocols` - (Optional) Set of protocols to inspect for, specified using the protocol's assigned internet protocol number (IANA). Network Firewall currently supports TCP only. Valid values: `6` * `source` - (Optional) Set of configuration blocks describing the source IP address and address ranges to inspect for, in CIDR notation. If not specified, this matches with any source address. See [Source](#source) below for details. From f38d7b9b50da6b459429c2e29157169fae9a7754 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 20 Jun 2024 14:02:54 -0400 Subject: [PATCH 45/68] AutoFlEx: Remove 'sliceOfPtrToList' and 'sliceOfPtrToSet'. --- internal/framework/flex/auto_flatten.go | 264 +++++++++--------------- 1 file changed, 97 insertions(+), 167 deletions(-) diff --git a/internal/framework/flex/auto_flatten.go b/internal/framework/flex/auto_flatten.go index 1acea96cd97..85c81aabda6 100644 --- a/internal/framework/flex/auto_flatten.go +++ b/internal/framework/flex/auto_flatten.go @@ -402,16 +402,16 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t switch tTo := tTo.(type) { case basetypes.ListTypable: // - // []int64 -> types.List(OfInt64). + // []int32 or []int64 -> types.List(OfInt64). // - diags.Append(sliceToList(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromReflectValue)...) + diags.Append(flattener.sliceOfPrimtiveToList(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ValueFromReflectValue)...) return diags case basetypes.SetTypable: // - // []int64 -> types.Set(OfInt64). + // []int32 or []int64 -> types.Set(OfInt64). // - diags.Append(sliceToSet(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromReflectValue)...) + diags.Append(flattener.sliceOfPrimitiveToSet(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ValueFromReflectValue)...) return diags } @@ -421,14 +421,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []string -> types.List(OfString). // - diags.Append(sliceToList(ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromReflectValue)...) + diags.Append(flattener.sliceOfPrimtiveToList(ctx, vFrom, tTo, vTo, types.StringType, newStringValueFromReflectValue)...) return diags case basetypes.SetTypable: // // []string -> types.Set(OfString). // - diags.Append(sliceToSet(ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromReflectValue)...) + diags.Append(flattener.sliceOfPrimitiveToSet(ctx, vFrom, tTo, vTo, types.StringType, newStringValueFromReflectValue)...) return diags } @@ -440,14 +440,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []*int32 -> types.List(OfInt64). // - diags.Append(sliceOfPtrToList[[]*int32](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt32PtrValue)...) + diags.Append(flattener.sliceOfPrimtiveToList(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ValueFromReflectPointerValue)...) return diags case basetypes.SetTypable: // // []*int32 -> types.Set(OfInt64). // - diags.Append(sliceOfPtrToSet[[]*int32](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt32PtrValue)...) + diags.Append(flattener.sliceOfPrimitiveToSet(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ValueFromReflectPointerValue)...) return diags } @@ -457,14 +457,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []*int64 -> types.List(OfInt64). // - diags.Append(sliceOfPtrToList[[]*int64](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt64PtrValue)...) + diags.Append(flattener.sliceOfPrimtiveToList(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ValueFromReflectPointerValue)...) return diags case basetypes.SetTypable: // // []*int64 -> types.Set(OfInt64). // - diags.Append(sliceOfPtrToSet[[]*int64](ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ElementFromGoInt64PtrValue)...) + diags.Append(flattener.sliceOfPrimitiveToSet(ctx, vFrom, tTo, vTo, types.Int64Type, newInt64ValueFromReflectPointerValue)...) return diags } @@ -474,14 +474,14 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []*string -> types.List(OfString). // - diags.Append(sliceOfPtrToList[[]*string](ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromGoStringPtrValue)...) + diags.Append(flattener.sliceOfPrimtiveToList(ctx, vFrom, tTo, vTo, types.StringType, newStringValueFromReflectPointerValue)...) return diags case basetypes.SetTypable: // // []*string -> types.Set(OfString). // - diags.Append(sliceOfPtrToSet[[]*string](ctx, vFrom, tTo, vTo, types.StringType, newStringElementFromGoStringPtrValue)...) + diags.Append(flattener.sliceOfPrimitiveToSet(ctx, vFrom, tTo, vTo, types.StringType, newStringValueFromReflectPointerValue)...) return diags } @@ -490,7 +490,7 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []*struct -> types.List(OfObject). // - diags.Append(flattener.sliceOfStructNestedObjectCollection(ctx, vFrom, tTo, vTo)...) + diags.Append(flattener.sliceOfStructToNestedObjectCollection(ctx, vFrom, tTo, vTo)...) return diags } } @@ -500,7 +500,7 @@ func (flattener autoFlattener) slice(ctx context.Context, vFrom reflect.Value, t // // []struct -> types.List(OfObject). // - diags.Append(flattener.sliceOfStructNestedObjectCollection(ctx, vFrom, tTo, vTo)...) + diags.Append(flattener.sliceOfStructToNestedObjectCollection(ctx, vFrom, tTo, vTo)...) return diags } @@ -828,108 +828,47 @@ func (flattener autoFlattener) structToNestedObject(ctx context.Context, vFrom r return diags } -// sliceOfStructNestedObjectCollection copies an AWS API []struct value to a compatible Plugin Framework NestedObjectCollectionValue value. -func (flattener autoFlattener) sliceOfStructNestedObjectCollection(ctx context.Context, vFrom reflect.Value, tTo fwtypes.NestedObjectCollectionType, vTo reflect.Value) diag.Diagnostics { +// sliceOfPrimtiveToList copies an AWS API slice of primitive (or pointer to primitive) value to a compatible Plugin Framework List value. +func (flattener autoFlattener) sliceOfPrimtiveToList(ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTypable, vTo reflect.Value, elementType attr.Type, f attrValueFromReflectValueFunc) diag.Diagnostics { var diags diag.Diagnostics if vFrom.IsNil() { - val, d := tTo.NullValue(ctx) + to, d := tTo.ValueFromList(ctx, types.ListNull(elementType)) diags.Append(d...) if diags.HasError() { return diags } - vTo.Set(reflect.ValueOf(val)) + vTo.Set(reflect.ValueOf(to)) return diags } - // Create a new target slice and flatten each element. - n := vFrom.Len() - to, d := tTo.NewObjectSlice(ctx, n, n) + elements := make([]attr.Value, vFrom.Len()) + for i := 0; i < vFrom.Len(); i++ { + elements[i] = f(vFrom.Index(i)) + } + list, d := types.ListValue(elementType, elements) diags.Append(d...) if diags.HasError() { return diags } - t := reflect.ValueOf(to) - for i := 0; i < n; i++ { - target, d := tTo.NewObjectPtr(ctx) - diags.Append(d...) - if diags.HasError() { - return diags - } - - diags.Append(autoFlexConvertStruct(ctx, vFrom.Index(i).Interface(), target, flattener)...) - if diags.HasError() { - return diags - } - - t.Index(i).Set(reflect.ValueOf(target)) - } - - // Set the target structure as a nested Object. - val, d := tTo.ValueFromObjectSlice(ctx, to) + to, d := tTo.ValueFromList(ctx, list) diags.Append(d...) if diags.HasError() { return diags } - vTo.Set(reflect.ValueOf(val)) - return diags -} - -// blockKeyMapSet takes a struct and assigns the value of the `key` -func blockKeyMapSet(to any, key reflect.Value) diag.Diagnostics { - var diags diag.Diagnostics - - valTo := reflect.ValueOf(to) - if kind := valTo.Kind(); kind == reflect.Ptr { - valTo = valTo.Elem() - } - - if valTo.Kind() != reflect.Struct { - diags.AddError("AutoFlEx", fmt.Sprintf("wrong type (%T), expected struct", valTo)) - return diags - } - - for i, typTo := 0, valTo.Type(); i < typTo.NumField(); i++ { - field := typTo.Field(i) - if field.PkgPath != "" { - continue // Skip unexported fields. - } - - if field.Name != MapBlockKey { - continue - } - - if _, ok := valTo.Field(i).Interface().(basetypes.StringValue); ok { - valTo.Field(i).Set(reflect.ValueOf(basetypes.NewStringValue(key.String()))) - return diags - } - - fieldType := valTo.Field(i).Type() - - method, found := fieldType.MethodByName("StringEnumValue") - if found { - result := fieldType.Method(method.Index).Func.Call([]reflect.Value{valTo.Field(i), key}) - if len(result) > 0 { - valTo.Field(i).Set(result[0]) - } - } - - return diags - } - - diags.AddError("AutoFlEx", fmt.Sprintf("unable to find map block key (%s)", MapBlockKey)) - + vTo.Set(reflect.ValueOf(to)) return diags } -func sliceToList(ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTypable, vTo reflect.Value, elementType attr.Type, f elementFromReflectValueFunc) diag.Diagnostics { +// sliceOfPrimitiveToSet copies an AWS API slice of primitive (or pointer to primitive) value to a compatible Plugin Framework Set value. +func (flattener autoFlattener) sliceOfPrimitiveToSet(ctx context.Context, vFrom reflect.Value, tTo basetypes.SetTypable, vTo reflect.Value, elementType attr.Type, f attrValueFromReflectValueFunc) diag.Diagnostics { var diags diag.Diagnostics if vFrom.IsNil() { - to, d := tTo.ValueFromList(ctx, types.ListNull(elementType)) + to, d := tTo.ValueFromSet(ctx, types.SetNull(elementType)) diags.Append(d...) if diags.HasError() { return diags @@ -943,13 +882,13 @@ func sliceToList(ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTyp for i := 0; i < vFrom.Len(); i++ { elements[i] = f(vFrom.Index(i)) } - list, d := types.ListValue(elementType, elements) + set, d := types.SetValue(elementType, elements) diags.Append(d...) if diags.HasError() { return diags } - to, d := tTo.ValueFromList(ctx, list) + to, d := tTo.ValueFromSet(ctx, set) diags.Append(d...) if diags.HasError() { return diags @@ -959,134 +898,125 @@ func sliceToList(ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTyp return diags } -func sliceOfPtrToList[S []E, E any](ctx context.Context, vFrom reflect.Value, tTo basetypes.ListTypable, vTo reflect.Value, elementType attr.Type, f elementFromGoValueFunc[E]) diag.Diagnostics { +// sliceOfStructToNestedObjectCollection copies an AWS API []struct value to a compatible Plugin Framework NestedObjectCollectionValue value. +func (flattener autoFlattener) sliceOfStructToNestedObjectCollection(ctx context.Context, vFrom reflect.Value, tTo fwtypes.NestedObjectCollectionType, vTo reflect.Value) diag.Diagnostics { var diags diag.Diagnostics if vFrom.IsNil() { - to, d := tTo.ValueFromList(ctx, types.ListNull(elementType)) + val, d := tTo.NullValue(ctx) diags.Append(d...) if diags.HasError() { return diags } - vTo.Set(reflect.ValueOf(to)) - return diags - } - - from := vFrom.Interface().(S) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = f(v) - } - list, d := types.ListValue(elementType, elements) - diags.Append(d...) - if diags.HasError() { + vTo.Set(reflect.ValueOf(val)) return diags } - to, d := tTo.ValueFromList(ctx, list) + // Create a new target slice and flatten each element. + n := vFrom.Len() + to, d := tTo.NewObjectSlice(ctx, n, n) diags.Append(d...) if diags.HasError() { return diags } - vTo.Set(reflect.ValueOf(to)) - return diags -} - -func sliceToSet(ctx context.Context, vFrom reflect.Value, tTo basetypes.SetTypable, vTo reflect.Value, elementType attr.Type, f elementFromReflectValueFunc) diag.Diagnostics { - var diags diag.Diagnostics - - if vFrom.IsNil() { - to, d := tTo.ValueFromSet(ctx, types.SetNull(elementType)) + t := reflect.ValueOf(to) + for i := 0; i < n; i++ { + target, d := tTo.NewObjectPtr(ctx) diags.Append(d...) if diags.HasError() { return diags } - vTo.Set(reflect.ValueOf(to)) - return diags - } + diags.Append(autoFlexConvertStruct(ctx, vFrom.Index(i).Interface(), target, flattener)...) + if diags.HasError() { + return diags + } - elements := make([]attr.Value, vFrom.Len()) - for i := 0; i < vFrom.Len(); i++ { - elements[i] = f(vFrom.Index(i)) - } - set, d := types.SetValue(elementType, elements) - diags.Append(d...) - if diags.HasError() { - return diags + t.Index(i).Set(reflect.ValueOf(target)) } - to, d := tTo.ValueFromSet(ctx, set) + // Set the target structure as a nested Object. + val, d := tTo.ValueFromObjectSlice(ctx, to) diags.Append(d...) if diags.HasError() { return diags } - vTo.Set(reflect.ValueOf(to)) + vTo.Set(reflect.ValueOf(val)) return diags } -func sliceOfPtrToSet[S []E, E any](ctx context.Context, vFrom reflect.Value, tTo basetypes.SetTypable, vTo reflect.Value, elementType attr.Type, f elementFromGoValueFunc[E]) diag.Diagnostics { +// blockKeyMapSet takes a struct and assigns the value of the `key` +func blockKeyMapSet(to any, key reflect.Value) diag.Diagnostics { var diags diag.Diagnostics - if vFrom.IsNil() { - to, d := tTo.ValueFromSet(ctx, types.SetNull(elementType)) - diags.Append(d...) - if diags.HasError() { - return diags - } - - vTo.Set(reflect.ValueOf(to)) - return diags + valTo := reflect.ValueOf(to) + if kind := valTo.Kind(); kind == reflect.Ptr { + valTo = valTo.Elem() } - from := vFrom.Interface().(S) - elements := make([]attr.Value, len(from)) - for i, v := range from { - elements[i] = f(v) - } - set, d := types.SetValue(elementType, elements) - diags.Append(d...) - if diags.HasError() { + if valTo.Kind() != reflect.Struct { + diags.AddError("AutoFlEx", fmt.Sprintf("wrong type (%T), expected struct", valTo)) return diags } - to, d := tTo.ValueFromSet(ctx, set) - diags.Append(d...) - if diags.HasError() { + for i, typTo := 0, valTo.Type(); i < typTo.NumField(); i++ { + field := typTo.Field(i) + if field.PkgPath != "" { + continue // Skip unexported fields. + } + + if field.Name != MapBlockKey { + continue + } + + if _, ok := valTo.Field(i).Interface().(basetypes.StringValue); ok { + valTo.Field(i).Set(reflect.ValueOf(basetypes.NewStringValue(key.String()))) + return diags + } + + fieldType := valTo.Field(i).Type() + + method, found := fieldType.MethodByName("StringEnumValue") + if found { + result := fieldType.Method(method.Index).Func.Call([]reflect.Value{valTo.Field(i), key}) + if len(result) > 0 { + valTo.Field(i).Set(result[0]) + } + } + return diags } - vTo.Set(reflect.ValueOf(to)) + diags.AddError("AutoFlEx", fmt.Sprintf("unable to find map block key (%s)", MapBlockKey)) + return diags } -type elementFromReflectValueFunc func(reflect.Value) attr.Value +type attrValueFromReflectValueFunc func(reflect.Value) attr.Value -func newInt64ElementFromReflectValue(vElem reflect.Value) attr.Value { - return types.Int64Value(vElem.Int()) +func newInt64ValueFromReflectValue(v reflect.Value) attr.Value { + return types.Int64Value(v.Int()) } -func newStringElementFromReflectValue(vElem reflect.Value) attr.Value { - return types.StringValue(vElem.String()) -} - -type elementFromGoValueFunc[T any] func(T) attr.Value - -func newInt64ElementFromGoInt32PtrValue(value *int32) attr.Value { - if value == nil { - return basetypes.NewInt64Null() +func newInt64ValueFromReflectPointerValue(v reflect.Value) attr.Value { + if v.IsNil() { + return types.Int64Null() } - return basetypes.NewInt64Value(int64(*value)) + return newInt64ValueFromReflectValue(v.Elem()) } -func newInt64ElementFromGoInt64PtrValue(value *int64) attr.Value { - return basetypes.NewInt64PointerValue(value) +func newStringValueFromReflectValue(v reflect.Value) attr.Value { + return types.StringValue(v.String()) } -func newStringElementFromGoStringPtrValue(value *string) attr.Value { - return basetypes.NewStringPointerValue(value) +func newStringValueFromReflectPointerValue(v reflect.Value) attr.Value { + if v.IsNil() { + return types.StringNull() + } + + return newStringValueFromReflectValue(v.Elem()) } From 0329d25756828d7f410501ae59196b71b9a42e84 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 20 Jun 2024 15:06:44 -0400 Subject: [PATCH 46/68] r/aws_networkfirewall_tls_inspection_configuration: Get tags working. --- .../networkfirewall/tls_inspection_configuration.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index 365c7d74c96..f0334021e53 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -298,6 +298,8 @@ func (r *tlsInspectionConfigurationResource) Create(ctx context.Context, request return } + input.Tags = getTagsIn(ctx) + outputC, err := conn.CreateTLSInspectionConfigurationWithContext(ctx, input) if err != nil { @@ -365,6 +367,8 @@ func (r *tlsInspectionConfigurationResource) Read(ctx context.Context, request r return } + setTagsOut(ctx, output.TLSInspectionConfigurationResponse.Tags) + response.Diagnostics.Append(response.State.Set(ctx, &data)...) } @@ -463,6 +467,10 @@ func (r *tlsInspectionConfigurationResource) ConfigValidators(context.Context) [ } } +func (r *tlsInspectionConfigurationResource) ModifyPlan(ctx context.Context, request resource.ModifyPlanRequest, response *resource.ModifyPlanResponse) { + r.SetTagsAll(ctx, request, response) +} + func findTLSInspectionConfigurationByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { input := &networkfirewall.DescribeTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(arn), From a5875b8336c746f54b6b3089dac8a19a1c03d70d Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 20 Jun 2024 15:10:27 -0400 Subject: [PATCH 47/68] Add 'TestAccNetworkFirewallTLSInspectionConfiguration_basic', 'TestAccNetworkFirewallTLSInspectionConfiguration_disappears' and 'TestAccNetworkFirewallTLSInspectionConfiguration_tags'. --- .../tls_inspection_configuration_test.go | 296 ++++++++++++++++-- 1 file changed, 262 insertions(+), 34 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 9655250e2d4..a726d05afd9 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -21,8 +21,136 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -// NOTE: acceptance tests require environment variable ACM_CERTIFICATE_ARN -// to be set and the ACM certificate to be validated during testing. +func TestAccNetworkFirewallTLSInspectionConfiguration_basic(t *testing.T) { + ctx := acctest.Context(t) + var v networkfirewall.DescribeTLSInspectionConfigurationOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + commonName := acctest.RandomDomain() + certificateDomainName := commonName.RandomSubdomain().String() + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_basic(rName, commonName.String(), certificateDomainName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + resource.TestCheckNoResourceAttr(resourceName, "certificate_authority"), + resource.TestCheckResourceAttr(resourceName, "certificates.#", acctest.Ct1), + resource.TestCheckNoResourceAttr(resourceName, names.AttrDescription), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.key_id", "AWS_OWNED_KMS_KEY"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "AWS_OWNED_KMS_KEY"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.#", acctest.Ct1), + resource.TestCheckNoResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.*", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.#", acctest.Ct1), + resource.TestCheckResourceAttrSet(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn"), + resource.TestCheckResourceAttrSet(resourceName, "tls_inspection_configuration_id"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"tls_inspection_configuration", "update_token"}, + }, + }, + }) +} + +func TestAccNetworkFirewallTLSInspectionConfiguration_disappears(t *testing.T) { + ctx := acctest.Context(t) + var v networkfirewall.DescribeTLSInspectionConfigurationOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + commonName := acctest.RandomDomain() + certificateDomainName := commonName.RandomSubdomain().String() + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_basic(rName, commonName.String(), certificateDomainName), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfnetworkfirewall.ResourceTLSInspectionConfiguration, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccNetworkFirewallTLSInspectionConfiguration_tags(t *testing.T) { + ctx := acctest.Context(t) + var v networkfirewall.DescribeTLSInspectionConfigurationOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + commonName := acctest.RandomDomain() + certificateDomainName := commonName.RandomSubdomain().String() + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_tags1(rName, commonName.String(), certificateDomainName, acctest.CtKey1, acctest.CtValue1), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"tls_inspection_configuration", "update_token"}, + }, + { + Config: testAccTLSInspectionConfigurationConfig_tags2(rName, commonName.String(), certificateDomainName, acctest.CtKey1, acctest.CtValue1Updated, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct2), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey1, acctest.CtValue1Updated), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + { + Config: testAccTLSInspectionConfigurationConfig_tags1(rName, commonName.String(), certificateDomainName, acctest.CtKey2, acctest.CtValue2), + Check: resource.ComposeTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsKey2, acctest.CtValue2), + ), + }, + }, + }) +} func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic(t *testing.T) { ctx := acctest.Context(t) @@ -335,38 +463,6 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfi }) } -func TestAccNetworkFirewallTLSInspectionConfiguration_disappears(t *testing.T) { - ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") - if certificateArn == "" { - t.Skipf("Environment variable %s is not set, skipping test", certificateArn) - } - - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_networkfirewall_tls_inspection_configuration.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateArn), - Check: resource.ComposeTestCheckFunc( - testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfnetworkfirewall.ResourceTLSInspectionConfiguration, resourceName), - ), - ExpectNonEmptyPlan: true, - }, - }, - }) -} - func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) @@ -414,6 +510,138 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, n string, } } +func testAccTLSInspectionConfigurationConfig_certificateBase(rName, commonName, certificateDomainName string) string { + return fmt.Sprintf(` +resource "aws_acmpca_certificate_authority" "test" { + permanent_deletion_time_in_days = 7 + type = "ROOT" + + certificate_authority_configuration { + key_algorithm = "RSA_4096" + signing_algorithm = "SHA512WITHRSA" + + subject { + common_name = %[2]q + } + } + + tags = { + Name = %[1]q + } +} + +resource "aws_acmpca_certificate" "test" { + certificate_authority_arn = aws_acmpca_certificate_authority.test.arn + certificate_signing_request = aws_acmpca_certificate_authority.test.certificate_signing_request + signing_algorithm = "SHA512WITHRSA" + + template_arn = "arn:${data.aws_partition.current.partition}:acm-pca:::template/RootCACertificate/V1" + + validity { + type = "YEARS" + value = 2 + } +} + +resource "aws_acmpca_certificate_authority_certificate" "test" { + certificate_authority_arn = aws_acmpca_certificate_authority.test.arn + + certificate = aws_acmpca_certificate.test.certificate + certificate_chain = aws_acmpca_certificate.test.certificate_chain +} + +data "aws_partition" "current" {} + +resource "aws_acm_certificate" "test" { + domain_name = %[3]q + certificate_authority_arn = aws_acmpca_certificate_authority.test.arn + + tags = { + Name = %[1]q + } + + depends_on = [ + aws_acmpca_certificate_authority_certificate.test, + ] +} +`, rName, commonName, certificateDomainName) +} + +func testAccTLSInspectionConfigurationConfig_basic(rName, commonName, certificateDomainName string) string { + return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_certificateBase(rName, commonName, certificateDomainName), fmt.Sprintf(` +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + + tls_inspection_configuration { + server_certificate_configuration { + server_certificate { + resource_arn = aws_acm_certificate.test.arn + } + scope { + protocols = [6] + destination { + address_definition = "0.0.0.0/0" + } + } + } + } +} +`, rName)) +} + +func testAccTLSInspectionConfigurationConfig_tags1(rName, commonName, certificateDomainName, tagKey1, tagValue1 string) string { + return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_certificateBase(rName, commonName, certificateDomainName), fmt.Sprintf(` +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + + tls_inspection_configuration { + server_certificate_configuration { + server_certificate { + resource_arn = aws_acm_certificate.test.arn + } + scope { + protocols = [6] + destination { + address_definition = "0.0.0.0/0" + } + } + } + } + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1)) +} + +func testAccTLSInspectionConfigurationConfig_tags2(rName, commonName, certificateDomainName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_certificateBase(rName, commonName, certificateDomainName), fmt.Sprintf(` +resource "aws_networkfirewall_tls_inspection_configuration" "test" { + name = %[1]q + + tls_inspection_configuration { + server_certificate_configuration { + server_certificate { + resource_arn = aws_acm_certificate.test.arn + } + scope { + protocols = [6] + destination { + address_definition = "0.0.0.0/0" + } + } + } + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2)) +} + func testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateARN, ca string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { From c2a61fbeea0b3f7d8ae68cfd7eb3989019ae655a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 20 Jun 2024 15:48:37 -0400 Subject: [PATCH 48/68] Add 'TestAccNetworkFirewallTLSInspectionConfiguration_encryptionConfiguration'. --- .../tls_inspection_configuration_test.go | 300 +++++++----------- 1 file changed, 108 insertions(+), 192 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index a726d05afd9..72380632ae2 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -152,6 +152,68 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_tags(t *testing.T) { }) } +func TestAccNetworkFirewallTLSInspectionConfiguration_encryptionConfiguration(t *testing.T) { + ctx := acctest.Context(t) + var v networkfirewall.DescribeTLSInspectionConfigurationOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + commonName := acctest.RandomDomain() + certificateDomainName := commonName.RandomSubdomain().String() + resourceName := "aws_networkfirewall_tls_inspection_configuration.test" + kmsKeyResourceName := "aws_kms_key.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName, commonName.String(), certificateDomainName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + resource.TestCheckNoResourceAttr(resourceName, "certificate_authority"), + resource.TestCheckResourceAttr(resourceName, "certificates.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", kmsKeyResourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.#", acctest.Ct1), + resource.TestCheckNoResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "8080"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.*", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "1024"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65534"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.#", acctest.Ct1), + resource.TestCheckResourceAttrSet(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn"), + resource.TestCheckResourceAttrSet(resourceName, "tls_inspection_configuration_id"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"tls_inspection_configuration", "update_token"}, + }, + }, + }) +} + func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -301,60 +363,6 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) }) } -func TestAccNetworkFirewallTLSInspectionConfiguration_egressWithEncryptionConfiguration(t *testing.T) { - ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - ca := os.Getenv("ACM_CA_CERTIFICATE_ARN") - if ca == "" { - t.Skipf("Environment variable %s is not set, skipping test", ca) - } - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_networkfirewall_tls_inspection_configuration.test" - keyName := "aws_kms_key.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccTLSInspectionConfigurationConfig_egressWithEncryptionConfiguration(rName, ca), - Check: resource.ComposeTestCheckFunc( - testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), - resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "update_token"), - resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), - resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, names.AttrARN), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", ca), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -410,59 +418,6 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) }) } -func TestAccNetworkFirewallTLSInspectionConfiguration_ingressWithEncryptionConfiguration(t *testing.T) { - ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") - if certificateArn == "" { - t.Skipf("Environment variable %s is not set, skipping test", certificateArn) - } - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_networkfirewall_tls_inspection_configuration.test" - keyName := "aws_kms_key.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccTLSInspectionConfigurationConfig_ingressWithEncryptionConfiguration(rName, certificateArn), - Check: resource.ComposeTestCheckFunc( - testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), - resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "update_token"), - resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), - resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", keyName, names.AttrARN), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", acctest.Ct0), - acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) @@ -642,91 +597,53 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { `, rName, tagKey1, tagValue1, tagKey2, tagValue2)) } -func testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateARN, ca string) string { - return fmt.Sprintf(` +func testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName, commonName, certificateDomainName string) string { + return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_certificateBase(rName, commonName, certificateDomainName), fmt.Sprintf(` +resource "aws_kms_key" "test" { + description = %[1]q + deletion_window_in_days = 7 +} + resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" + encryption_configuration { - key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" + key_id = aws_kms_key.test.arn + type = "CUSTOMER_KMS" } + tls_inspection_configuration { server_certificate_configuration { - certificate_authority_arn = %[3]q - check_certificate_revocation_status { - revoked_status_action = "REJECT" - unknown_status_action = "PASS" - } server_certificate { - resource_arn = %[2]q + resource_arn = aws_acm_certificate.test.arn } scope { protocols = [6] - destination_ports { - from_port = 443 - to_port = 443 - } + destination { address_definition = "0.0.0.0/0" } - source_ports { - from_port = 0 - to_port = 65535 - } - source { - address_definition = "0.0.0.0/0" - } - } - } - } -} -`, rName, certificateARN, ca) -} - -func testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateARN, ca string) string { - return fmt.Sprintf(` -resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q - description = "test" - encryption_configuration { - key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" - } - tls_inspection_configuration { - server_certificate_configuration { - certificate_authority_arn = %[3]q - check_certificate_revocation_status { - revoked_status_action = "PASS" - unknown_status_action = "REJECT" - } - server_certificate { - resource_arn = %[2]q - } - scope { - protocols = [6] destination_ports { from_port = 443 to_port = 8080 } - destination { + + source { address_definition = "10.0.0.0/8" } source_ports { from_port = 1024 to_port = 65534 } - source { - address_definition = "10.0.0.0/8" - } } } } } -`, rName, certificateARN, ca) +`, rName)) } -func testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateARN string) string { +func testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateARN, ca string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q @@ -737,6 +654,11 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } tls_inspection_configuration { server_certificate_configuration { + certificate_authority_arn = %[3]q + check_certificate_revocation_status { + revoked_status_action = "REJECT" + unknown_status_action = "PASS" + } server_certificate { resource_arn = %[2]q } @@ -760,29 +682,25 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } } -`, rName, certificateARN) +`, rName, certificateARN, ca) } -func testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName string) string { +func testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateARN, ca string) string { return fmt.Sprintf(` -resource "aws_kms_key" "test" { - description = %[1]q - deletion_window_in_days = 7 -} -`, rName) -} - -func testAccTLSInspectionConfigurationConfig_ingressWithEncryptionConfiguration(rName, certificateARN string) string { - return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName), fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" encryption_configuration { - key_id = aws_kms_key.test.arn - type = "CUSTOMER_KMS" + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { server_certificate_configuration { + certificate_authority_arn = %[3]q + check_certificate_revocation_status { + revoked_status_action = "PASS" + unknown_status_action = "REJECT" + } server_certificate { resource_arn = %[2]q } @@ -790,26 +708,26 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { protocols = [6] destination_ports { from_port = 443 - to_port = 443 + to_port = 8080 } destination { - address_definition = "0.0.0.0/0" + address_definition = "10.0.0.0/8" } source_ports { - from_port = 0 - to_port = 65535 + from_port = 1024 + to_port = 65534 } source { - address_definition = "0.0.0.0/0" + address_definition = "10.0.0.0/8" } } } } } -`, rName, certificateARN)) +`, rName, certificateARN, ca) } -func testAccTLSInspectionConfigurationConfig_egressBasic(rName, ca string) string { +func testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateARN string) string { return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q @@ -820,10 +738,8 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } tls_inspection_configuration { server_certificate_configuration { - certificate_authority_arn = %[2]q - check_certificate_revocation_status { - revoked_status_action = "REJECT" - unknown_status_action = "PASS" + server_certificate { + resource_arn = %[2]q } scope { protocols = [6] @@ -845,17 +761,17 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } } -`, rName, ca) +`, rName, certificateARN) } -func testAccTLSInspectionConfigurationConfig_egressWithEncryptionConfiguration(rName, ca string) string { - return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_encryptionConfiguration(rName), fmt.Sprintf(` +func testAccTLSInspectionConfigurationConfig_egressBasic(rName, ca string) string { + return fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" encryption_configuration { - key_id = aws_kms_key.test.arn - type = "CUSTOMER_KMS" + key_id = "AWS_OWNED_KMS_KEY" + type = "AWS_OWNED_KMS_KEY" } tls_inspection_configuration { server_certificate_configuration { @@ -884,5 +800,5 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { } } } -`, rName, ca)) +`, rName, ca) } From 64b8daa58be90f9937557b035402d1ddac98491a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 20 Jun 2024 17:16:26 -0400 Subject: [PATCH 49/68] Add 'TestAccNetworkFirewallTLSInspectionConfiguration_checkCertificateRevocationStatus'. --- .../tls_inspection_configuration_test.go | 364 ++++-------------- 1 file changed, 72 insertions(+), 292 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index 72380632ae2..f5082aeaaf4 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -6,7 +6,6 @@ package networkfirewall_test import ( "context" "fmt" - "os" "testing" "github.com/YakDriver/regexache" @@ -176,8 +175,8 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_encryptionConfiguration(t resource.TestCheckResourceAttr(resourceName, "certificates.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), resource.TestCheckResourceAttr(resourceName, "encryption_configuration.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), resource.TestCheckTypeSetElemAttrPair(resourceName, "encryption_configuration.0.key_id", kmsKeyResourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "CUSTOMER_KMS"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), @@ -214,22 +213,12 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_encryptionConfiguration(t }) } -func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic(t *testing.T) { +func TestAccNetworkFirewallTLSInspectionConfiguration_checkCertificateRevocationStatus(t *testing.T) { ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") - if certificateArn == "" { - t.Skipf("Environment variable %s is not set, skipping test", certificateArn) - } - caCertificateArn := os.Getenv("ACM_CA_CERTIFICATE_ARN") - if certificateArn == "" { - t.Skipf("Environment variable %s is not set, skipping test", caCertificateArn) - } + var v networkfirewall.DescribeTLSInspectionConfigurationOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + commonName := acctest.RandomDomain() + certificateDomainName := commonName.RandomSubdomain().String() resourceName := "aws_networkfirewall_tls_inspection_configuration.test" resource.ParallelTest(t, resource.TestCase{ @@ -239,181 +228,87 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_combinedIngressEgressBasic CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateArn, caCertificateArn), - Check: resource.ComposeTestCheckFunc( - testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + Config: testAccTLSInspectionConfigurationConfig_checkCertificateRevocationStatus(rName, commonName.String(), certificateDomainName, "REJECT", "PASS"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + resource.TestCheckNoResourceAttr(resourceName, "certificate_authority"), + resource.TestCheckResourceAttr(resourceName, "certificates.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.key_id", "AWS_OWNED_KMS_KEY"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "AWS_OWNED_KMS_KEY"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), - resource.TestCheckResourceAttrSet(resourceName, "update_token"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", - }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", caCertificateArn), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.#", acctest.Ct1), + resource.TestCheckNoResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), - acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateArn, caCertificateArn), - Check: resource.ComposeTestCheckFunc( - testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), - resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), - resource.TestCheckResourceAttrSet(resourceName, "update_token"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", - }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "8080"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.*", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "1024"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65534"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", caCertificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "PASS"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "REJECT"), - acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.#", acctest.Ct1), + resource.TestCheckResourceAttrSet(resourceName, "tls_inspection_configuration_id"), + resource.TestCheckResourceAttrSet(resourceName, "update_token"), ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"tls_inspection_configuration", "update_token"}, }, - }, - }) -} - -func TestAccNetworkFirewallTLSInspectionConfiguration_egressBasic(t *testing.T) { - ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - ca := os.Getenv("ACM_CA_CERTIFICATE_ARN") - if ca == "" { - t.Skipf("Environment variable %s is not set, skipping test", ca) - } - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_networkfirewall_tls_inspection_configuration.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), - Steps: []resource.TestStep{ { - Config: testAccTLSInspectionConfigurationConfig_egressBasic(rName, ca), - Check: resource.ComposeTestCheckFunc( - testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + Config: testAccTLSInspectionConfigurationConfig_checkCertificateRevocationStatus(rName, commonName.String(), certificateDomainName, "DROP", "PASS"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &v), + acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), + resource.TestCheckNoResourceAttr(resourceName, "certificate_authority"), + resource.TestCheckResourceAttr(resourceName, "certificates.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.key_id", "AWS_OWNED_KMS_KEY"), + resource.TestCheckResourceAttr(resourceName, "encryption_configuration.0.type", "AWS_OWNED_KMS_KEY"), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), - resource.TestCheckResourceAttrSet(resourceName, "update_token"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", - }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn", ca), + resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.#", acctest.Ct1), + resource.TestCheckNoResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.certificate_authority_arn"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "REJECT"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.revoked_status_action", "DROP"), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.0.unknown_status_action", "PASS"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccNetworkFirewallTLSInspectionConfiguration_ingressBasic(t *testing.T) { - ctx := acctest.Context(t) - if testing.Short() { - t.Skip("skipping long-running test in short mode") - } - - var tlsinspectionconfiguration networkfirewall.DescribeTLSInspectionConfigurationOutput - certificateArn := os.Getenv("ACM_CERTIFICATE_ARN") - if certificateArn == "" { - t.Skipf("Environment variable %s is not set, skipping test", certificateArn) - } - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - resourceName := "aws_networkfirewall_tls_inspection_configuration.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.NetworkFirewall), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckTLSInspectionConfigurationDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateArn), - Check: resource.ComposeTestCheckFunc( - testAccCheckTLSInspectionConfigurationExists(ctx, resourceName, &tlsinspectionconfiguration), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrDescription, "test"), - resource.TestCheckResourceAttrSet(resourceName, "number_of_associations"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "8080"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.#", acctest.Ct1), + resource.TestCheckTypeSetElemAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.*", "6"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "10.0.0.0/8"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.#", acctest.Ct1), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", "1024"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65534"), + resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.#", acctest.Ct1), + resource.TestCheckResourceAttrSet(resourceName, "tls_inspection_configuration_id"), resource.TestCheckResourceAttrSet(resourceName, "update_token"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "encryption_configuration.*", map[string]string{ - names.AttrKeyID: "AWS_OWNED_KMS_KEY", - names.AttrType: "AWS_OWNED_KMS_KEY", - }), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.server_certificate.0.resource_arn", certificateArn), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.from_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.destination_ports.0.to_port", "443"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.protocols.0", "6"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source.0.address_definition", "0.0.0.0/0"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.from_port", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.scope.0.source_ports.0.to_port", "65535"), - resource.TestCheckResourceAttr(resourceName, "tls_inspection_configuration.0.server_certificate_configuration.0.check_certificate_revocation_status.#", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "certificate_authority.#", acctest.Ct0), - resource.TestCheckResourceAttr(resourceName, "certificates.#", acctest.Ct1), - acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", regexache.MustCompile(`tls-configuration/+.`)), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, }, }) } @@ -643,162 +538,47 @@ resource "aws_networkfirewall_tls_inspection_configuration" "test" { `, rName)) } -func testAccTLSInspectionConfigurationConfig_combinedIngressEgress(rName, certificateARN, ca string) string { - return fmt.Sprintf(` +func testAccTLSInspectionConfigurationConfig_checkCertificateRevocationStatus(rName, commonName, certificateDomainName, revokedStatusAction, unknownStatusAction string) string { + return acctest.ConfigCompose(testAccTLSInspectionConfigurationConfig_certificateBase(rName, commonName, certificateDomainName), fmt.Sprintf(` resource "aws_networkfirewall_tls_inspection_configuration" "test" { name = %[1]q description = "test" + encryption_configuration { key_id = "AWS_OWNED_KMS_KEY" type = "AWS_OWNED_KMS_KEY" } + tls_inspection_configuration { server_certificate_configuration { - certificate_authority_arn = %[3]q check_certificate_revocation_status { - revoked_status_action = "REJECT" - unknown_status_action = "PASS" + revoked_status_action = %[2]q + unknown_status_action = %[3]q } server_certificate { - resource_arn = %[2]q + resource_arn = aws_acm_certificate.test.arn } scope { protocols = [6] - destination_ports { - from_port = 443 - to_port = 443 - } + destination { address_definition = "0.0.0.0/0" } - source_ports { - from_port = 0 - to_port = 65535 - } - source { - address_definition = "0.0.0.0/0" - } - } - } - } -} -`, rName, certificateARN, ca) -} - -func testAccTLSInspectionConfigurationConfig_combinedIngressEgressUpdate(rName, certificateARN, ca string) string { - return fmt.Sprintf(` -resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q - description = "test" - encryption_configuration { - key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" - } - tls_inspection_configuration { - server_certificate_configuration { - certificate_authority_arn = %[3]q - check_certificate_revocation_status { - revoked_status_action = "PASS" - unknown_status_action = "REJECT" - } - server_certificate { - resource_arn = %[2]q - } - scope { - protocols = [6] destination_ports { from_port = 443 to_port = 8080 } - destination { + + source { address_definition = "10.0.0.0/8" } source_ports { from_port = 1024 to_port = 65534 } - source { - address_definition = "10.0.0.0/8" - } - } - } - } -} -`, rName, certificateARN, ca) -} - -func testAccTLSInspectionConfigurationConfig_ingressBasic(rName, certificateARN string) string { - return fmt.Sprintf(` -resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q - description = "test" - encryption_configuration { - key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" - } - tls_inspection_configuration { - server_certificate_configuration { - server_certificate { - resource_arn = %[2]q - } - scope { - protocols = [6] - destination_ports { - from_port = 443 - to_port = 443 - } - destination { - address_definition = "0.0.0.0/0" - } - source_ports { - from_port = 0 - to_port = 65535 - } - source { - address_definition = "0.0.0.0/0" - } - } - } - } -} -`, rName, certificateARN) -} - -func testAccTLSInspectionConfigurationConfig_egressBasic(rName, ca string) string { - return fmt.Sprintf(` -resource "aws_networkfirewall_tls_inspection_configuration" "test" { - name = %[1]q - description = "test" - encryption_configuration { - key_id = "AWS_OWNED_KMS_KEY" - type = "AWS_OWNED_KMS_KEY" - } - tls_inspection_configuration { - server_certificate_configuration { - certificate_authority_arn = %[2]q - check_certificate_revocation_status { - revoked_status_action = "REJECT" - unknown_status_action = "PASS" - } - scope { - protocols = [6] - destination_ports { - from_port = 443 - to_port = 443 - } - destination { - address_definition = "0.0.0.0/0" - } - source_ports { - from_port = 0 - to_port = 65535 - } - source { - address_definition = "0.0.0.0/0" - } } } } } -`, rName, ca) +`, rName, revokedStatusAction, unknownStatusAction)) } From 72ab61dcba74037e6b23749e96475930163a26f5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 20 Jun 2024 17:18:37 -0400 Subject: [PATCH 50/68] networkfirewall: Use AWS SDK for Go v2. --- internal/conns/awsclient_gen.go | 6 +- internal/service/networkfirewall/generate.go | 2 +- .../service_endpoints_gen_test.go | 147 ++++++++++++++---- .../networkfirewall/service_package_gen.go | 36 ++--- internal/service/networkfirewall/tags_gen.go | 36 ++--- names/data/names_data.hcl | 2 +- 6 files changed, 160 insertions(+), 69 deletions(-) diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index 14a2b6eec00..c7a3894ffd2 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -124,6 +124,7 @@ import ( mq_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mq" mwaa_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mwaa" neptunegraph_sdkv2 "github.com/aws/aws-sdk-go-v2/service/neptunegraph" + networkfirewall_sdkv2 "github.com/aws/aws-sdk-go-v2/service/networkfirewall" oam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/oam" opensearchserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/opensearchserverless" organizations_sdkv2 "github.com/aws/aws-sdk-go-v2/service/organizations" @@ -230,7 +231,6 @@ import ( managedgrafana_sdkv1 "github.com/aws/aws-sdk-go/service/managedgrafana" memorydb_sdkv1 "github.com/aws/aws-sdk-go/service/memorydb" neptune_sdkv1 "github.com/aws/aws-sdk-go/service/neptune" - networkfirewall_sdkv1 "github.com/aws/aws-sdk-go/service/networkfirewall" networkmanager_sdkv1 "github.com/aws/aws-sdk-go/service/networkmanager" opensearchservice_sdkv1 "github.com/aws/aws-sdk-go/service/opensearchservice" opsworks_sdkv1 "github.com/aws/aws-sdk-go/service/opsworks" @@ -908,8 +908,8 @@ func (c *AWSClient) NeptuneGraphClient(ctx context.Context) *neptunegraph_sdkv2. return errs.Must(client[*neptunegraph_sdkv2.Client](ctx, c, names.NeptuneGraph, make(map[string]any))) } -func (c *AWSClient) NetworkFirewallConn(ctx context.Context) *networkfirewall_sdkv1.NetworkFirewall { - return errs.Must(conn[*networkfirewall_sdkv1.NetworkFirewall](ctx, c, names.NetworkFirewall, make(map[string]any))) +func (c *AWSClient) NetworkFirewallClient(ctx context.Context) *networkfirewall_sdkv2.Client { + return errs.Must(client[*networkfirewall_sdkv2.Client](ctx, c, names.NetworkFirewall, make(map[string]any))) } func (c *AWSClient) NetworkManagerConn(ctx context.Context) *networkmanager_sdkv1.NetworkManager { diff --git a/internal/service/networkfirewall/generate.go b/internal/service/networkfirewall/generate.go index 98d7418946b..eab93db6667 100644 --- a/internal/service/networkfirewall/generate.go +++ b/internal/service/networkfirewall/generate.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/tags/main.go -ListTags -ServiceTagsSlice -UpdateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTags -ServiceTagsSlice -UpdateTags //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. diff --git a/internal/service/networkfirewall/service_endpoints_gen_test.go b/internal/service/networkfirewall/service_endpoints_gen_test.go index f61943cd786..9e8b33ce37d 100644 --- a/internal/service/networkfirewall/service_endpoints_gen_test.go +++ b/internal/service/networkfirewall/service_endpoints_gen_test.go @@ -4,17 +4,20 @@ package networkfirewall_test import ( "context" + "errors" "fmt" "maps" - "net/url" "os" "path/filepath" + "reflect" "strings" "testing" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/endpoints" - networkfirewall_sdkv1 "github.com/aws/aws-sdk-go/service/networkfirewall" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + networkfirewall_sdkv2 "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" "github.com/google/go-cmp/cmp" "github.com/hashicorp/aws-sdk-go-base/v2/servicemocks" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -239,54 +242,63 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } func defaultEndpoint(region string) string { - r := endpoints.DefaultResolver() + r := networkfirewall_sdkv2.NewDefaultEndpointResolverV2() - ep, err := r.EndpointFor(networkfirewall_sdkv1.EndpointsID, region) + ep, err := r.ResolveEndpoint(context.Background(), networkfirewall_sdkv2.EndpointParameters{ + Region: aws_sdkv2.String(region), + }) if err != nil { return err.Error() } - url, _ := url.Parse(ep.URL) - - if url.Path == "" { - url.Path = "/" + if ep.URI.Path == "" { + ep.URI.Path = "/" } - return url.String() + return ep.URI.String() } func defaultFIPSEndpoint(region string) string { - r := endpoints.DefaultResolver() + r := networkfirewall_sdkv2.NewDefaultEndpointResolverV2() - ep, err := r.EndpointFor(networkfirewall_sdkv1.EndpointsID, region, func(opt *endpoints.Options) { - opt.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled + ep, err := r.ResolveEndpoint(context.Background(), networkfirewall_sdkv2.EndpointParameters{ + Region: aws_sdkv2.String(region), + UseFIPS: aws_sdkv2.Bool(true), }) if err != nil { return err.Error() } - url, _ := url.Parse(ep.URL) - - if url.Path == "" { - url.Path = "/" + if ep.URI.Path == "" { + ep.URI.Path = "/" } - return url.String() + return ep.URI.String() } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) apiCallParams { t.Helper() - client := meta.NetworkFirewallConn(ctx) + client := meta.NetworkFirewallClient(ctx) - req, _ := client.ListFirewallsRequest(&networkfirewall_sdkv1.ListFirewallsInput{}) + var result apiCallParams - req.HTTPRequest.URL.Path = "/" - - return apiCallParams{ - endpoint: req.HTTPRequest.URL.String(), - region: aws_sdkv1.StringValue(client.Config.Region), + _, err := client.ListFirewalls(ctx, &networkfirewall_sdkv2.ListFirewallsInput{}, + func(opts *networkfirewall_sdkv2.Options) { + opts.APIOptions = append(opts.APIOptions, + addRetrieveEndpointURLMiddleware(t, &result.endpoint), + addRetrieveRegionMiddleware(&result.region), + addCancelRequestMiddleware(), + ) + }, + ) + if err == nil { + t.Fatal("Expected an error, got none") + } else if !errors.Is(err, errCancelOperation) { + t.Fatalf("Unexpected error: %s", err) } + + return result } func withNoConfig(_ *caseSetup) { @@ -443,6 +455,89 @@ func testEndpointCase(t *testing.T, region string, testcase endpointTestCase, ca } } +func addRetrieveEndpointURLMiddleware(t *testing.T, endpoint *string) func(*middleware.Stack) error { + return func(stack *middleware.Stack) error { + return stack.Finalize.Add( + retrieveEndpointURLMiddleware(t, endpoint), + middleware.After, + ) + } +} + +func retrieveEndpointURLMiddleware(t *testing.T, endpoint *string) middleware.FinalizeMiddleware { + return middleware.FinalizeMiddlewareFunc( + "Test: Retrieve Endpoint", + func(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (middleware.FinalizeOutput, middleware.Metadata, error) { + t.Helper() + + request, ok := in.Request.(*smithyhttp.Request) + if !ok { + t.Fatalf("Expected *github.com/aws/smithy-go/transport/http.Request, got %s", fullTypeName(in.Request)) + } + + url := request.URL + url.RawQuery = "" + url.Path = "/" + + *endpoint = url.String() + + return next.HandleFinalize(ctx, in) + }) +} + +func addRetrieveRegionMiddleware(region *string) func(*middleware.Stack) error { + return func(stack *middleware.Stack) error { + return stack.Serialize.Add( + retrieveRegionMiddleware(region), + middleware.After, + ) + } +} + +func retrieveRegionMiddleware(region *string) middleware.SerializeMiddleware { + return middleware.SerializeMiddlewareFunc( + "Test: Retrieve Region", + func(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) (middleware.SerializeOutput, middleware.Metadata, error) { + *region = awsmiddleware.GetRegion(ctx) + + return next.HandleSerialize(ctx, in) + }, + ) +} + +var errCancelOperation = fmt.Errorf("Test: Canceling request") + +func addCancelRequestMiddleware() func(*middleware.Stack) error { + return func(stack *middleware.Stack) error { + return stack.Finalize.Add( + cancelRequestMiddleware(), + middleware.After, + ) + } +} + +// cancelRequestMiddleware creates a Smithy middleware that intercepts the request before sending and cancels it +func cancelRequestMiddleware() middleware.FinalizeMiddleware { + return middleware.FinalizeMiddlewareFunc( + "Test: Cancel Requests", + func(_ context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (middleware.FinalizeOutput, middleware.Metadata, error) { + return middleware.FinalizeOutput{}, middleware.Metadata{}, errCancelOperation + }) +} + +func fullTypeName(i interface{}) string { + return fullValueTypeName(reflect.ValueOf(i)) +} + +func fullValueTypeName(v reflect.Value) string { + if v.Kind() == reflect.Ptr { + return "*" + fullValueTypeName(reflect.Indirect(v)) + } + + requestType := v.Type() + return fmt.Sprintf("%s.%s", requestType.PkgPath(), requestType.Name()) +} + func generateSharedConfigFile(config configFile) string { var buf strings.Builder diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index fb8f458a59c..90a2a182547 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -5,10 +5,8 @@ package networkfirewall import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - endpoints_sdkv1 "github.com/aws/aws-sdk-go/aws/endpoints" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - networkfirewall_sdkv1 "github.com/aws/aws-sdk-go/service/networkfirewall" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + networkfirewall_sdkv2 "github.com/aws/aws-sdk-go-v2/service/networkfirewall" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" @@ -91,25 +89,23 @@ func (p *servicePackage) ServicePackageName() string { return names.NetworkFirewall } -// NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*networkfirewall_sdkv1.NetworkFirewall, error) { - sess := config[names.AttrSession].(*session_sdkv1.Session) +// NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*networkfirewall_sdkv2.Client, error) { + cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - cfg := aws_sdkv1.Config{} + return networkfirewall_sdkv2.NewFromConfig(cfg, func(o *networkfirewall_sdkv2.Options) { + if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { + tflog.Debug(ctx, "setting endpoint", map[string]any{ + "tf_aws.endpoint": endpoint, + }) + o.BaseEndpoint = aws_sdkv2.String(endpoint) - if endpoint := config[names.AttrEndpoint].(string); endpoint != "" { - tflog.Debug(ctx, "setting endpoint", map[string]any{ - "tf_aws.endpoint": endpoint, - }) - cfg.Endpoint = aws_sdkv1.String(endpoint) - - if sess.Config.UseFIPSEndpoint == endpoints_sdkv1.FIPSEndpointStateEnabled { - tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") - cfg.UseFIPSEndpoint = endpoints_sdkv1.FIPSEndpointStateDisabled + if o.EndpointOptions.UseFIPSEndpoint == aws_sdkv2.FIPSEndpointStateEnabled { + tflog.Debug(ctx, "endpoint set, ignoring UseFIPSEndpoint setting") + o.EndpointOptions.UseFIPSEndpoint = aws_sdkv2.FIPSEndpointStateDisabled + } } - } - - return networkfirewall_sdkv1.New(sess.Copy(&cfg)), nil + }), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/networkfirewall/tags_gen.go b/internal/service/networkfirewall/tags_gen.go index 7ef08be33ec..50cf108ade5 100644 --- a/internal/service/networkfirewall/tags_gen.go +++ b/internal/service/networkfirewall/tags_gen.go @@ -5,9 +5,9 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/aws/aws-sdk-go/service/networkfirewall/networkfirewalliface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/logging" @@ -19,12 +19,12 @@ import ( // listTags lists networkfirewall service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func listTags(ctx context.Context, conn networkfirewalliface.NetworkFirewallAPI, identifier string) (tftags.KeyValueTags, error) { +func listTags(ctx context.Context, conn *networkfirewall.Client, identifier string, optFns ...func(*networkfirewall.Options)) (tftags.KeyValueTags, error) { input := &networkfirewall.ListTagsForResourceInput{ ResourceArn: aws.String(identifier), } - output, err := conn.ListTagsForResourceWithContext(ctx, input) + output, err := conn.ListTagsForResource(ctx, input, optFns...) if err != nil { return tftags.New(ctx, nil), err @@ -36,7 +36,7 @@ func listTags(ctx context.Context, conn networkfirewalliface.NetworkFirewallAPI, // ListTags lists networkfirewall service tags and set them in Context. // It is called from outside this package. func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { - tags, err := listTags(ctx, meta.(*conns.AWSClient).NetworkFirewallConn(ctx), identifier) + tags, err := listTags(ctx, meta.(*conns.AWSClient).NetworkFirewallClient(ctx), identifier) if err != nil { return err @@ -52,11 +52,11 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier stri // []*SERVICE.Tag handling // Tags returns networkfirewall service tags. -func Tags(tags tftags.KeyValueTags) []*networkfirewall.Tag { - result := make([]*networkfirewall.Tag, 0, len(tags)) +func Tags(tags tftags.KeyValueTags) []awstypes.Tag { + result := make([]awstypes.Tag, 0, len(tags)) for k, v := range tags.Map() { - tag := &networkfirewall.Tag{ + tag := awstypes.Tag{ Key: aws.String(k), Value: aws.String(v), } @@ -68,11 +68,11 @@ func Tags(tags tftags.KeyValueTags) []*networkfirewall.Tag { } // KeyValueTags creates tftags.KeyValueTags from networkfirewall service tags. -func KeyValueTags(ctx context.Context, tags []*networkfirewall.Tag) tftags.KeyValueTags { +func KeyValueTags(ctx context.Context, tags []awstypes.Tag) tftags.KeyValueTags { m := make(map[string]*string, len(tags)) for _, tag := range tags { - m[aws.StringValue(tag.Key)] = tag.Value + m[aws.ToString(tag.Key)] = tag.Value } return tftags.New(ctx, m) @@ -80,7 +80,7 @@ func KeyValueTags(ctx context.Context, tags []*networkfirewall.Tag) tftags.KeyVa // getTagsIn returns networkfirewall service tags from Context. // nil is returned if there are no input tags. -func getTagsIn(ctx context.Context) []*networkfirewall.Tag { +func getTagsIn(ctx context.Context) []awstypes.Tag { if inContext, ok := tftags.FromContext(ctx); ok { if tags := Tags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { return tags @@ -91,7 +91,7 @@ func getTagsIn(ctx context.Context) []*networkfirewall.Tag { } // setTagsOut sets networkfirewall service tags in Context. -func setTagsOut(ctx context.Context, tags []*networkfirewall.Tag) { +func setTagsOut(ctx context.Context, tags []awstypes.Tag) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = option.Some(KeyValueTags(ctx, tags)) } @@ -100,7 +100,7 @@ func setTagsOut(ctx context.Context, tags []*networkfirewall.Tag) { // updateTags updates networkfirewall service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func updateTags(ctx context.Context, conn networkfirewalliface.NetworkFirewallAPI, identifier string, oldTagsMap, newTagsMap any) error { +func updateTags(ctx context.Context, conn *networkfirewall.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*networkfirewall.Options)) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -111,10 +111,10 @@ func updateTags(ctx context.Context, conn networkfirewalliface.NetworkFirewallAP if len(removedTags) > 0 { input := &networkfirewall.UntagResourceInput{ ResourceArn: aws.String(identifier), - TagKeys: aws.StringSlice(removedTags.Keys()), + TagKeys: removedTags.Keys(), } - _, err := conn.UntagResourceWithContext(ctx, input) + _, err := conn.UntagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("untagging resource (%s): %w", identifier, err) @@ -129,7 +129,7 @@ func updateTags(ctx context.Context, conn networkfirewalliface.NetworkFirewallAP Tags: Tags(updatedTags), } - _, err := conn.TagResourceWithContext(ctx, input) + _, err := conn.TagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("tagging resource (%s): %w", identifier, err) @@ -142,5 +142,5 @@ func updateTags(ctx context.Context, conn networkfirewalliface.NetworkFirewallAP // UpdateTags updates networkfirewall service tags. // It is called from outside this package. func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { - return updateTags(ctx, meta.(*conns.AWSClient).NetworkFirewallConn(ctx), identifier, oldTags, newTags) + return updateTags(ctx, meta.(*conns.AWSClient).NetworkFirewallClient(ctx), identifier, oldTags, newTags) } diff --git a/names/data/names_data.hcl b/names/data/names_data.hcl index 3880af55ab7..a852b9bedec 100644 --- a/names/data/names_data.hcl +++ b/names/data/names_data.hcl @@ -6440,7 +6440,7 @@ service "networkfirewall" { sdk { id = "Network Firewall" - client_version = [1] + client_version = [2] } names { From 07ad52b883019f0dc4dc56ddc8f739ef9e8dd5ea Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Thu, 20 Jun 2024 17:20:06 -0400 Subject: [PATCH 51/68] Run 'go get github.com/aws/aws-sdk-go-v2/service/networkfirewall@v1.39.1 && go mod tidy'. --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 440fb568e12..14b30cabb56 100644 --- a/go.mod +++ b/go.mod @@ -132,6 +132,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/mq v1.23.1 github.com/aws/aws-sdk-go-v2/service/mwaa v1.28.1 github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.9.1 + github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.39.1 github.com/aws/aws-sdk-go-v2/service/oam v1.12.1 github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.12.1 github.com/aws/aws-sdk-go-v2/service/organizations v1.28.1 diff --git a/go.sum b/go.sum index d82438079ca..981ec8fbe8a 100644 --- a/go.sum +++ b/go.sum @@ -294,6 +294,8 @@ github.com/aws/aws-sdk-go-v2/service/mwaa v1.28.1 h1:fzBc0gfOfrlcyP/COVDt8iGVUnQ github.com/aws/aws-sdk-go-v2/service/mwaa v1.28.1/go.mod h1:a46hMp6jog7U6rhMxmp0wwcGvPTJINQkc6EevZb7SNs= github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.9.1 h1:UjByGYRBlhjY4l8Lun62K3Z62Wks84q3UasnDDJoz5I= github.com/aws/aws-sdk-go-v2/service/neptunegraph v1.9.1/go.mod h1:5q3YTQennpO1/KB7rU71vW/9PjLC4PuosEi2xDEw5OY= +github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.39.1 h1:f2TcduRAvOs8ltPaAnjSP64WHRmM/B5bsDSqXRYBYGs= +github.com/aws/aws-sdk-go-v2/service/networkfirewall v1.39.1/go.mod h1:23qyfghRkv9qOMRIL9KdUHiKyhARU/0FddRMtvMSVV0= github.com/aws/aws-sdk-go-v2/service/oam v1.12.1 h1:LZrULRkfrmZVE8OHqwI8tKFEFxpjZl6ll7Bn2MCCVwg= github.com/aws/aws-sdk-go-v2/service/oam v1.12.1/go.mod h1:yiUaEYA1zVxtz/EGgf8NE7rT56sLKGqQwQrWg/GhGu8= github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.12.1 h1:BRAM7tTwHJojSOhiyUkPh2Z/hOco7OkayTf6MYFOF5w= From f63671d223f6e492407fdbd6a16556eb919652a6 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 09:01:28 -0400 Subject: [PATCH 52/68] r/aws_networkfirewall_tls_inspection_configuration: Migrate to AWS SDK for Go v2. --- .../tls_inspection_configuration.go | 66 +++++++++---------- .../tls_inspection_configuration_test.go | 6 +- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index f0334021e53..a83324f9a7b 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -9,8 +9,9 @@ import ( "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" @@ -28,6 +29,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/enum" "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag" "github.com/hashicorp/terraform-provider-aws/internal/framework" @@ -158,16 +160,12 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ "revoked_status_action": schema.StringAttribute{ - Optional: true, - Validators: []validator.String{ - stringvalidator.OneOf(networkfirewall.RevocationCheckAction_Values()...), - }, + CustomType: fwtypes.StringEnumType[awstypes.RevocationCheckAction](), + Optional: true, }, "unknown_status_action": schema.StringAttribute{ - Optional: true, - Validators: []validator.String{ - stringvalidator.OneOf(networkfirewall.RevocationCheckAction_Values()...), - }, + CustomType: fwtypes.StringEnumType[awstypes.RevocationCheckAction](), + Optional: true, }, }, }, @@ -289,7 +287,7 @@ func (r *tlsInspectionConfigurationResource) Create(ctx context.Context, request return } - conn := r.Meta().NetworkFirewallConn(ctx) + conn := r.Meta().NetworkFirewallClient(ctx) name := data.TLSInspectionConfigurationName.ValueString() input := &networkfirewall.CreateTLSInspectionConfigurationInput{} @@ -300,7 +298,7 @@ func (r *tlsInspectionConfigurationResource) Create(ctx context.Context, request input.Tags = getTagsIn(ctx) - outputC, err := conn.CreateTLSInspectionConfigurationWithContext(ctx, input) + outputC, err := conn.CreateTLSInspectionConfiguration(ctx, input) if err != nil { response.Diagnostics.AddError(fmt.Sprintf("creating NetworkFirewall TLS Inspection Configuration (%s)", name), err.Error()) @@ -344,7 +342,7 @@ func (r *tlsInspectionConfigurationResource) Read(ctx context.Context, request r return } - conn := r.Meta().NetworkFirewallConn(ctx) + conn := r.Meta().NetworkFirewallClient(ctx) output, err := findTLSInspectionConfigurationByARN(ctx, conn, data.ID.ValueString()) @@ -383,7 +381,7 @@ func (r *tlsInspectionConfigurationResource) Update(ctx context.Context, request return } - conn := r.Meta().NetworkFirewallConn(ctx) + conn := r.Meta().NetworkFirewallClient(ctx) if !new.Description.Equal(old.Description) || !new.EncryptionConfiguration.Equal(old.EncryptionConfiguration) || @@ -396,7 +394,7 @@ func (r *tlsInspectionConfigurationResource) Update(ctx context.Context, request input.UpdateToken = aws.String(old.UpdateToken.ValueString()) - output, err := conn.UpdateTLSInspectionConfigurationWithContext(ctx, input) + output, err := conn.UpdateTLSInspectionConfiguration(ctx, input) if err != nil { response.Diagnostics.AddError(fmt.Sprintf("updating NetworkFirewall TLS Inspection Configuration (%s)", new.ID.ValueString()), err.Error()) @@ -435,13 +433,13 @@ func (r *tlsInspectionConfigurationResource) Delete(ctx context.Context, request return } - conn := r.Meta().NetworkFirewallConn(ctx) + conn := r.Meta().NetworkFirewallClient(ctx) - _, err := conn.DeleteTLSInspectionConfigurationWithContext(ctx, &networkfirewall.DeleteTLSInspectionConfigurationInput{ + _, err := conn.DeleteTLSInspectionConfiguration(ctx, &networkfirewall.DeleteTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(data.ID.ValueString()), }) - if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return } @@ -471,14 +469,14 @@ func (r *tlsInspectionConfigurationResource) ModifyPlan(ctx context.Context, req r.SetTagsAll(ctx, request, response) } -func findTLSInspectionConfigurationByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { +func findTLSInspectionConfigurationByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { input := &networkfirewall.DescribeTLSInspectionConfigurationInput{ TLSInspectionConfigurationArn: aws.String(arn), } - output, err := conn.DescribeTLSInspectionConfigurationWithContext(ctx, input) + output, err := conn.DescribeTLSInspectionConfiguration(ctx, input) - if errs.IsA[*networkfirewall.ResourceNotFoundException](err) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -496,7 +494,7 @@ func findTLSInspectionConfigurationByARN(ctx context.Context, conn *networkfirew return output, nil } -func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { +func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { output, err := findTLSInspectionConfigurationByARN(ctx, conn, arn) @@ -508,7 +506,7 @@ func statusTLSInspectionConfiguration(ctx context.Context, conn *networkfirewall return nil, "", err } - return output, aws.StringValue(output.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus), nil + return output, string(output.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus), nil } } @@ -516,7 +514,7 @@ const ( resourceStatusPending = "PENDING" ) -func statusTLSInspectionConfigurationCertificates(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { +func statusTLSInspectionConfigurationCertificates(ctx context.Context, conn *networkfirewall.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { output, err := findTLSInspectionConfigurationByARN(ctx, conn, arn) @@ -534,18 +532,18 @@ func statusTLSInspectionConfigurationCertificates(ctx context.Context, conn *net // The API does not immediately return data for certificates and certificate authority even when the resource status is "ACTIVE", // which causes unexpected diffs when reading. This sets the status to "PENDING" until either the certificates or the certificate // authority is populated (the API will always return at least one of the two). - if status := aws.StringValue(output.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus); status == networkfirewall.ResourceStatusActive && (certificates != nil || certificateAuthority != nil) { - return output, status, nil + if status := output.TLSInspectionConfigurationResponse.TLSInspectionConfigurationStatus; status == awstypes.ResourceStatusActive && (certificates != nil || certificateAuthority != nil) { + return output, string(status), nil } return output, resourceStatusPending, nil } } -func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { +func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfirewall.Client, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { stateConf := &retry.StateChangeConf{ Pending: []string{resourceStatusPending}, - Target: []string{networkfirewall.ResourceStatusActive}, + Target: enum.Slice(awstypes.ResourceStatusActive), Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), Timeout: timeout, } @@ -559,10 +557,10 @@ func waitTLSInspectionConfigurationCreated(ctx context.Context, conn *networkfir return nil, err } -func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { +func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfirewall.Client, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { stateConf := &retry.StateChangeConf{ Pending: []string{resourceStatusPending}, - Target: []string{networkfirewall.ResourceStatusActive}, + Target: enum.Slice(awstypes.ResourceStatusActive), Refresh: statusTLSInspectionConfigurationCertificates(ctx, conn, arn), Timeout: timeout, } @@ -576,9 +574,9 @@ func waitTLSInspectionConfigurationUpdated(ctx context.Context, conn *networkfir return nil, err } -func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { +func waitTLSInspectionConfigurationDeleted(ctx context.Context, conn *networkfirewall.Client, arn string, timeout time.Duration) (*networkfirewall.DescribeTLSInspectionConfigurationOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{networkfirewall.ResourceStatusActive, networkfirewall.ResourceStatusDeleting}, + Pending: enum.Slice(awstypes.ResourceStatusActive, awstypes.ResourceStatusDeleting), Target: []string{}, Refresh: statusTLSInspectionConfiguration(ctx, conn, arn), Timeout: timeout, @@ -655,8 +653,8 @@ type serverCertificateConfigurationModel struct { } type checkCertificateRevocationStatusActionsModel struct { - RevokedStatusAction types.String `tfsdk:"revoked_status_action"` - UnknownStatusAction types.String `tfsdk:"unknown_status_action"` + RevokedStatusAction fwtypes.StringEnum[awstypes.RevocationCheckAction] `tfsdk:"revoked_status_action"` + UnknownStatusAction fwtypes.StringEnum[awstypes.RevocationCheckAction] `tfsdk:"unknown_status_action"` } type serverCertificateScopeModel struct { diff --git a/internal/service/networkfirewall/tls_inspection_configuration_test.go b/internal/service/networkfirewall/tls_inspection_configuration_test.go index f5082aeaaf4..6ce206e9bea 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration_test.go +++ b/internal/service/networkfirewall/tls_inspection_configuration_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -315,7 +315,7 @@ func TestAccNetworkFirewallTLSInspectionConfiguration_checkCertificateRevocation func testAccCheckTLSInspectionConfigurationDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_networkfirewall_tls_inspection_configuration" { @@ -346,7 +346,7 @@ func testAccCheckTLSInspectionConfigurationExists(ctx context.Context, n string, return fmt.Errorf("Not found: %s", n) } - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) output, err := tfnetworkfirewall.FindTLSInspectionConfigurationByARN(ctx, conn, rs.Primary.ID) From 4d525cfa559f7747208a2a139bb4451b92ba9922 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 09:50:06 -0400 Subject: [PATCH 53/68] r/aws_networkfirewall_logging_configuration: Migrate to AWS SDK for Go v2. --- .changelog/35168.txt | 4 + .../service/networkfirewall/exports_test.go | 2 + internal/service/networkfirewall/find.go | 14 - .../networkfirewall/logging_configuration.go | 287 ++++++++++-------- .../logging_configuration_test.go | 265 +++++++--------- .../networkfirewall/service_package_gen.go | 3 +- 6 files changed, 268 insertions(+), 307 deletions(-) diff --git a/.changelog/35168.txt b/.changelog/35168.txt index 4fbe7f14ec8..f633690a19c 100644 --- a/.changelog/35168.txt +++ b/.changelog/35168.txt @@ -1,3 +1,7 @@ ```release-note:new-resource aws_networkfirewall_tls_inspection_configuration +``` + +```release-note:enhancement +resource/aws_networkfirewall_logging_configuration: Add plan-time validation of `firewall_arn` ``` \ No newline at end of file diff --git a/internal/service/networkfirewall/exports_test.go b/internal/service/networkfirewall/exports_test.go index 91246b3d0d8..5d4fc7059fc 100644 --- a/internal/service/networkfirewall/exports_test.go +++ b/internal/service/networkfirewall/exports_test.go @@ -5,7 +5,9 @@ package networkfirewall // Exports for use in tests only. var ( + ResourceLoggingConfiguration = resourceLoggingConfiguration ResourceTLSInspectionConfiguration = newTLSInspectionConfigurationResource + FindLoggingConfigurationByARN = findLoggingConfigurationByARN FindTLSInspectionConfigurationByARN = findTLSInspectionConfigurationByARN ) diff --git a/internal/service/networkfirewall/find.go b/internal/service/networkfirewall/find.go index 16815140437..aafe1476376 100644 --- a/internal/service/networkfirewall/find.go +++ b/internal/service/networkfirewall/find.go @@ -10,20 +10,6 @@ import ( "github.com/aws/aws-sdk-go/service/networkfirewall" ) -// FindLoggingConfiguration returns the LoggingConfigurationOutput from a call to DescribeLoggingConfigurationWithContext -// given the context and FindFirewall ARN. -// Returns nil if the FindLoggingConfiguration is not found. -func FindLoggingConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeLoggingConfigurationOutput, error) { - input := &networkfirewall.DescribeLoggingConfigurationInput{ - FirewallArn: aws.String(arn), - } - output, err := conn.DescribeLoggingConfigurationWithContext(ctx, input) - if err != nil { - return nil, err - } - return output, nil -} - // FindFirewallPolicyByNameAndARN returns the FirewallPolicyOutput from a call to DescribeFirewallPolicyWithContext // given the context and at least one of FirewallPolicyArn and FirewallPolicyName. func FindFirewallPolicyByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, name string) (*networkfirewall.DescribeFirewallPolicyOutput, error) { diff --git a/internal/service/networkfirewall/logging_configuration.go b/internal/service/networkfirewall/logging_configuration.go index 5844aa053ff..904612e4226 100644 --- a/internal/service/networkfirewall/logging_configuration.go +++ b/internal/service/networkfirewall/logging_configuration.go @@ -9,19 +9,24 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "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/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/flex" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) -// @SDKResource("aws_networkfirewall_logging_configuration") -func ResourceLoggingConfiguration() *schema.Resource { +// @SDKResource("aws_networkfirewall_logging_configuration", name="Logging Configuration") +func resourceLoggingConfiguration() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceLoggingConfigurationCreate, ReadWithoutTimeout: resourceLoggingConfigurationRead, @@ -34,9 +39,10 @@ func ResourceLoggingConfiguration() *schema.Resource { Schema: map[string]*schema.Schema{ "firewall_arn": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, }, names.AttrLoggingConfiguration: { Type: schema.TypeList, @@ -58,14 +64,14 @@ func ResourceLoggingConfiguration() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, }, "log_destination_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.LogDestinationType_Values(), false), + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.LogDestinationType](), }, "log_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.LogType_Values(), false), + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.LogType](), }, }, }, @@ -79,48 +85,36 @@ func ResourceLoggingConfiguration() *schema.Resource { func resourceLoggingConfigurationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - firewallArn := d.Get("firewall_arn").(string) - - log.Printf("[DEBUG] Adding Logging Configuration to NetworkFirewall Firewall: %s", firewallArn) - - loggingConfigs := expandLoggingConfiguration(d.Get(names.AttrLoggingConfiguration).([]interface{})) - // cumulatively add the configured "log_destination_config" in "logging_configuration" - err := putLoggingConfiguration(ctx, conn, firewallArn, loggingConfigs) - if err != nil { + firewallARN := d.Get("firewall_arn").(string) + loggingConfigs := expandLoggingConfigurations(d.Get(names.AttrLoggingConfiguration).([]interface{})) + if err := addLoggingConfigurations(ctx, conn, firewallARN, loggingConfigs); err != nil { return sdkdiag.AppendFromErr(diags, err) } - d.SetId(firewallArn) + d.SetId(firewallARN) return append(diags, resourceLoggingConfigurationRead(ctx, d, meta)...) } func resourceLoggingConfigurationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + output, err := findLoggingConfigurationByARN(ctx, conn, d.Id()) - log.Printf("[DEBUG] Reading Logging Configuration for NetworkFirewall Firewall: %s", d.Id()) - - output, err := FindLoggingConfiguration(ctx, conn, d.Id()) - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { - log.Printf("[WARN] Logging Configuration for NetworkFirewall Firewall (%s) not found, removing from state", d.Id()) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] NetworkFirewall Logging Configuration (%s) not found, removing from state", d.Id()) d.SetId("") return diags } if err != nil { - return sdkdiag.AppendErrorf(diags, "reading Logging Configuration for NetworkFirewall Firewall: %s: %s", d.Id(), err) - } - - if output == nil { - return sdkdiag.AppendErrorf(diags, "reading Logging Configuration for NetworkFirewall Firewall: %s: empty output", d.Id()) + return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Logging Configuration (%s): %s", d.Id(), err) } d.Set("firewall_arn", output.FirewallArn) - if err := d.Set(names.AttrLoggingConfiguration, flattenLoggingConfiguration(output.LoggingConfiguration)); err != nil { return sdkdiag.AppendErrorf(diags, "setting logging_configuration: %s", err) } @@ -130,28 +124,23 @@ func resourceLoggingConfigurationRead(ctx context.Context, d *schema.ResourceDat func resourceLoggingConfigurationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - - log.Printf("[DEBUG] Updating Logging Configuration for NetworkFirewall Firewall: %s", d.Id()) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) o, n := d.GetChange(names.AttrLoggingConfiguration) - // Remove destination configs one by one, if any + + // Remove destination configs one by one, if any. if oldConfig := o.([]interface{}); len(oldConfig) != 0 && oldConfig[0] != nil { - loggingConfig := expandLoggingConfigurationOnUpdate(oldConfig) - if loggingConfig != nil { - err := removeLoggingConfiguration(ctx, conn, d.Id(), loggingConfig) - if err != nil { + if loggingConfig := expandLoggingConfigurationOnUpdate(oldConfig); loggingConfig != nil { + if err := removeLoggingConfiguration(ctx, conn, d.Id(), loggingConfig); err != nil { return sdkdiag.AppendFromErr(diags, err) } } } - // Only send new LoggingConfiguration with content + + // Only send new LoggingConfiguration with content. if newConfig := n.([]interface{}); len(newConfig) != 0 && newConfig[0] != nil { - loggingConfigs := expandLoggingConfiguration(d.Get(names.AttrLoggingConfiguration).([]interface{})) - // cumulatively add the configured "log_destination_config" in "logging_configuration" - err := putLoggingConfiguration(ctx, conn, d.Id(), loggingConfigs) - if err != nil { + loggingConfigs := expandLoggingConfigurations(d.Get(names.AttrLoggingConfiguration).([]interface{})) + if err := addLoggingConfigurations(ctx, conn, d.Id(), loggingConfigs); err != nil { return sdkdiag.AppendFromErr(diags, err) } } @@ -161,21 +150,21 @@ func resourceLoggingConfigurationUpdate(ctx context.Context, d *schema.ResourceD func resourceLoggingConfigurationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + output, err := findLoggingConfigurationByARN(ctx, conn, d.Id()) - log.Printf("[DEBUG] Deleting Logging Configuration for NetworkFirewall Firewall: %s", d.Id()) - output, err := FindLoggingConfiguration(ctx, conn, d.Id()) - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if tfresource.NotFound(err) { return diags } if err != nil { - return sdkdiag.AppendErrorf(diags, "deleting Logging Configuration for NetworkFirewall Firewall: %s: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Logging Configuration (%s): %s", d.Id(), err) } if output != nil && output.LoggingConfiguration != nil { - err := removeLoggingConfiguration(ctx, conn, aws.StringValue(output.FirewallArn), output.LoggingConfiguration) + log.Printf("[DEBUG] Deleting NetworkFirewall Logging Configuration: %s", d.Id()) + err := removeLoggingConfiguration(ctx, conn, d.Id(), output.LoggingConfiguration) if err != nil { return sdkdiag.AppendFromErr(diags, err) } @@ -184,166 +173,204 @@ func resourceLoggingConfigurationDelete(ctx context.Context, d *schema.ResourceD return diags } -func putLoggingConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, l []*networkfirewall.LoggingConfiguration) error { +func addLoggingConfigurations(ctx context.Context, conn *networkfirewall.Client, arn string, loggingConfigs []*awstypes.LoggingConfiguration) error { var errs []error - for _, config := range l { + for _, loggingConfig := range loggingConfigs { input := &networkfirewall.UpdateLoggingConfigurationInput{ FirewallArn: aws.String(arn), - LoggingConfiguration: config, + LoggingConfiguration: loggingConfig, } - _, err := conn.UpdateLoggingConfigurationWithContext(ctx, input) + _, err := conn.UpdateLoggingConfiguration(ctx, input) if err != nil { - errs = append(errs, fmt.Errorf("adding Logging Configuration to NetworkFirewall Firewall (%s): %w", arn, err)) + errs = append(errs, fmt.Errorf("adding NetworkFirewall Logging Configuration (%s): %w", arn, err)) } } return errors.Join(errs...) } -func removeLoggingConfiguration(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, l *networkfirewall.LoggingConfiguration) error { - if l == nil { +func removeLoggingConfiguration(ctx context.Context, conn *networkfirewall.Client, arn string, loggingConfig *awstypes.LoggingConfiguration) error { + if loggingConfig == nil { return nil } var errs []error - // Must delete destination configs one at a time - for i, config := range l.LogDestinationConfigs { + // Must delete destination configs one at a time. + for i, logDestinationConfig := range loggingConfig.LogDestinationConfigs { input := &networkfirewall.UpdateLoggingConfigurationInput{ FirewallArn: aws.String(arn), } - if i == 0 && len(l.LogDestinationConfigs) == 2 { - loggingConfig := &networkfirewall.LoggingConfiguration{ - LogDestinationConfigs: []*networkfirewall.LogDestinationConfig{config}, + if i == 0 && len(loggingConfig.LogDestinationConfigs) == 2 { + loggingConfig := &awstypes.LoggingConfiguration{ + LogDestinationConfigs: []awstypes.LogDestinationConfig{logDestinationConfig}, } input.LoggingConfiguration = loggingConfig } - _, err := conn.UpdateLoggingConfigurationWithContext(ctx, input) + _, err := conn.UpdateLoggingConfiguration(ctx, input) if err != nil { - errs = append(errs, fmt.Errorf("removing Logging Configuration LogDestinationConfig (%v) from NetworkFirewall Firewall: %s: %w", config, arn, err)) + errs = append(errs, fmt.Errorf("removing NetworkFirewall Logging Configuration (%s): %w", arn, err)) } } return errors.Join(errs...) } -func expandLoggingConfiguration(l []interface{}) []*networkfirewall.LoggingConfiguration { - if len(l) == 0 || l[0] == nil { +func findLoggingConfigurationByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeLoggingConfigurationOutput, error) { + input := &networkfirewall.DescribeLoggingConfigurationInput{ + FirewallArn: aws.String(arn), + } + + output, err := conn.DescribeLoggingConfiguration(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.LoggingConfiguration == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} + +func expandLoggingConfigurations(tfList []interface{}) []*awstypes.LoggingConfiguration { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - loggingConfigs := make([]*networkfirewall.LoggingConfiguration, 0) - if tfSet, ok := tfMap["log_destination_config"].(*schema.Set); ok && tfSet.Len() > 0 { - tfList := tfSet.List() - for _, tfMapRaw := range tfList { + apiObjects := make([]*awstypes.LoggingConfiguration, 0) + + if v, ok := tfMap["log_destination_config"].(*schema.Set); ok && v.Len() > 0 { + for _, tfMapRaw := range v.List() { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - config := &networkfirewall.LogDestinationConfig{} + + logDestinationConfig := awstypes.LogDestinationConfig{} + if v, ok := tfMap["log_destination"].(map[string]interface{}); ok && len(v) > 0 { - config.LogDestination = aws.StringMap(expandLogDestinationConfigLogDestination(v)) + logDestinationConfig.LogDestination = flex.ExpandStringValueMap(v) } if v, ok := tfMap["log_destination_type"].(string); ok && v != "" { - config.LogDestinationType = aws.String(v) + logDestinationConfig.LogDestinationType = awstypes.LogDestinationType(v) } if v, ok := tfMap["log_type"].(string); ok && v != "" { - config.LogType = aws.String(v) + logDestinationConfig.LogType = awstypes.LogType(v) } - // exclude empty LogDestinationConfig due to TypeMap in TypeSet behavior - // Related: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 - if config.LogDestination == nil && config.LogDestinationType == nil && config.LogType == nil { + + // Exclude empty LogDestinationConfig due to TypeMap in TypeSet behavior. + // Related: https://github.com/hashicorp/terraform-plugin-sdk/issues/588. + if logDestinationConfig.LogDestination == nil && logDestinationConfig.LogDestinationType == "" && logDestinationConfig.LogType == "" { continue } - loggingConfig := &networkfirewall.LoggingConfiguration{} - // include all (max 2) "log_destination_config" i.e. prepend the already-expanded loggingConfig - if len(loggingConfigs) == 1 && len(loggingConfigs[0].LogDestinationConfigs) == 1 { - loggingConfig.LogDestinationConfigs = append(loggingConfig.LogDestinationConfigs, loggingConfigs[0].LogDestinationConfigs[0]) + + apiObject := &awstypes.LoggingConfiguration{} + // Include all (max 2) "log_destination_config" i.e. prepend the already-expanded loggingConfig. + if len(apiObjects) == 1 && len(apiObjects[0].LogDestinationConfigs) == 1 { + apiObject.LogDestinationConfigs = append(apiObject.LogDestinationConfigs, apiObjects[0].LogDestinationConfigs[0]) } - loggingConfig.LogDestinationConfigs = append(loggingConfig.LogDestinationConfigs, config) - loggingConfigs = append(loggingConfigs, loggingConfig) + apiObject.LogDestinationConfigs = append(apiObject.LogDestinationConfigs, logDestinationConfig) + + apiObjects = append(apiObjects, apiObject) } } - return loggingConfigs + + return apiObjects } -func expandLoggingConfigurationOnUpdate(l []interface{}) *networkfirewall.LoggingConfiguration { - if len(l) == 0 || l[0] == nil { +func expandLoggingConfigurationOnUpdate(tfList []interface{}) *awstypes.LoggingConfiguration { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - loggingConfig := &networkfirewall.LoggingConfiguration{} - if tfSet, ok := tfMap["log_destination_config"].(*schema.Set); ok && tfSet.Len() > 0 { - tfList := tfSet.List() - destConfigs := make([]*networkfirewall.LogDestinationConfig, 0, len(tfList)) + apiObject := &awstypes.LoggingConfiguration{} + + if v, ok := tfMap["log_destination_config"].(*schema.Set); ok && v.Len() > 0 { + tfList := v.List() + logDestinationConfigs := make([]awstypes.LogDestinationConfig, 0, len(tfList)) + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - config := &networkfirewall.LogDestinationConfig{} + + logDestinationConfig := awstypes.LogDestinationConfig{} + if v, ok := tfMap["log_destination"].(map[string]interface{}); ok && len(v) > 0 { - config.LogDestination = aws.StringMap(expandLogDestinationConfigLogDestination(v)) + logDestinationConfig.LogDestination = flex.ExpandStringValueMap(v) } if v, ok := tfMap["log_destination_type"].(string); ok && v != "" { - config.LogDestinationType = aws.String(v) + logDestinationConfig.LogDestinationType = awstypes.LogDestinationType(v) } if v, ok := tfMap["log_type"].(string); ok && v != "" { - config.LogType = aws.String(v) + logDestinationConfig.LogType = awstypes.LogType(v) } - // exclude empty LogDestinationConfig due to TypeMap in TypeSet behavior - // Related: https://github.com/hashicorp/terraform-plugin-sdk/issues/588 - if config.LogDestination == nil && config.LogDestinationType == nil && config.LogType == nil { + + // Exclude empty LogDestinationConfig due to TypeMap in TypeSet behavior. + // Related: https://github.com/hashicorp/terraform-plugin-sdk/issues/588. + if logDestinationConfig.LogDestination == nil && logDestinationConfig.LogDestinationType == "" && logDestinationConfig.LogType == "" { continue } - destConfigs = append(destConfigs, config) + + logDestinationConfigs = append(logDestinationConfigs, logDestinationConfig) } - loggingConfig.LogDestinationConfigs = destConfigs - } - return loggingConfig -} -func expandLogDestinationConfigLogDestination(dst map[string]interface{}) map[string]string { - m := map[string]string{} - for k, v := range dst { - m[k] = v.(string) + apiObject.LogDestinationConfigs = logDestinationConfigs } - return m + + return apiObject } -func flattenLoggingConfiguration(lc *networkfirewall.LoggingConfiguration) []interface{} { - if lc == nil || lc.LogDestinationConfigs == nil { +func flattenLoggingConfiguration(apiObject *awstypes.LoggingConfiguration) []interface{} { + if apiObject == nil || apiObject.LogDestinationConfigs == nil { return []interface{}{} } - m := map[string]interface{}{ - "log_destination_config": flattenLoggingConfigurationLogDestinationConfigs(lc.LogDestinationConfigs), + + tfMap := map[string]interface{}{ + "log_destination_config": flattenLoggingConfigurationLogDestinationConfigs(apiObject.LogDestinationConfigs), } - return []interface{}{m} + + return []interface{}{tfMap} } -func flattenLoggingConfigurationLogDestinationConfigs(configs []*networkfirewall.LogDestinationConfig) []interface{} { - l := make([]interface{}, 0, len(configs)) - for _, config := range configs { - m := map[string]interface{}{ - "log_destination": aws.StringValueMap(config.LogDestination), - "log_destination_type": aws.StringValue(config.LogDestinationType), - "log_type": aws.StringValue(config.LogType), +func flattenLoggingConfigurationLogDestinationConfigs(apiObjects []awstypes.LogDestinationConfig) []interface{} { + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + "log_destination": apiObject.LogDestination, + "log_destination_type": apiObject.LogDestinationType, + "log_type": apiObject.LogType, } - l = append(l, m) + + tfList = append(tfList, tfMap) } - return l + + return tfList } diff --git a/internal/service/networkfirewall/logging_configuration_test.go b/internal/service/networkfirewall/logging_configuration_test.go index f16bbe82199..bd804e4838c 100644 --- a/internal/service/networkfirewall/logging_configuration_test.go +++ b/internal/service/networkfirewall/logging_configuration_test.go @@ -8,14 +8,14 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfnetworkfirewall "github.com/hashicorp/terraform-provider-aws/internal/service/networkfirewall" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -33,26 +33,26 @@ func TestAccNetworkFirewallLoggingConfiguration_CloudWatchLogDestination_logGrou CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, networkfirewall.LogDestinationTypeCloudWatchLogs, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.logGroup": logGroupName, - "log_destination_type": networkfirewall.LogDestinationTypeCloudWatchLogs, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), }), ), }, { - Config: testAccLoggingConfigurationConfig_cloudWatch(updatedLogGroupName, rName, networkfirewall.LogDestinationTypeCloudWatchLogs, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_cloudWatch(updatedLogGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.logGroup": updatedLogGroupName, - "log_destination_type": networkfirewall.LogDestinationTypeCloudWatchLogs, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), }), ), }, @@ -78,22 +78,22 @@ func TestAccNetworkFirewallLoggingConfiguration_CloudWatchLogDestination_logType CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, networkfirewall.LogDestinationTypeCloudWatchLogs, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ - "log_type": networkfirewall.LogTypeFlow, + "log_type": string(awstypes.LogTypeFlow), }), ), }, { - Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, networkfirewall.LogDestinationTypeCloudWatchLogs, networkfirewall.LogTypeAlert), + Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeAlert)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ - "log_type": networkfirewall.LogTypeAlert, + "log_type": string(awstypes.LogTypeAlert), }), ), }, @@ -120,26 +120,26 @@ func TestAccNetworkFirewallLoggingConfiguration_KinesisLogDestination_deliverySt CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, networkfirewall.LogDestinationTypeKinesisDataFirehose, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, string(awstypes.LogDestinationTypeKinesisDataFirehose), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.deliveryStream": streamName, - "log_destination_type": networkfirewall.LogDestinationTypeKinesisDataFirehose, + "log_destination_type": string(awstypes.LogDestinationTypeKinesisDataFirehose), }), ), }, { - Config: testAccLoggingConfigurationConfig_kinesis(updatedStreamName, rName, networkfirewall.LogDestinationTypeKinesisDataFirehose, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_kinesis(updatedStreamName, rName, string(awstypes.LogDestinationTypeKinesisDataFirehose), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.deliveryStream": updatedStreamName, - "log_destination_type": networkfirewall.LogDestinationTypeKinesisDataFirehose, + "log_destination_type": string(awstypes.LogDestinationTypeKinesisDataFirehose), }), ), }, @@ -165,22 +165,22 @@ func TestAccNetworkFirewallLoggingConfiguration_KinesisLogDestination_logType(t CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, networkfirewall.LogDestinationTypeKinesisDataFirehose, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, string(awstypes.LogDestinationTypeKinesisDataFirehose), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ - "log_type": networkfirewall.LogTypeFlow, + "log_type": string(awstypes.LogTypeFlow), }), ), }, { - Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, networkfirewall.LogDestinationTypeKinesisDataFirehose, networkfirewall.LogTypeAlert), + Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, string(awstypes.LogDestinationTypeKinesisDataFirehose), string(awstypes.LogTypeAlert)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ - "log_type": networkfirewall.LogTypeAlert, + "log_type": string(awstypes.LogTypeAlert), }), ), }, @@ -208,7 +208,7 @@ func TestAccNetworkFirewallLoggingConfiguration_S3LogDestination_bucketName(t *t Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -219,7 +219,7 @@ func TestAccNetworkFirewallLoggingConfiguration_S3LogDestination_bucketName(t *t ), }, { - Config: testAccLoggingConfigurationConfig_s3(updatedBucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3(updatedBucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -252,22 +252,22 @@ func TestAccNetworkFirewallLoggingConfiguration_S3LogDestination_logType(t *test Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ - "log_type": networkfirewall.LogTypeFlow, + "log_type": string(awstypes.LogTypeFlow), }), ), }, { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeAlert), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeAlert)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ - "log_type": networkfirewall.LogTypeAlert, + "log_type": string(awstypes.LogTypeAlert), }), ), }, @@ -294,7 +294,7 @@ func TestAccNetworkFirewallLoggingConfiguration_S3LogDestination_prefix(t *testi Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -305,7 +305,7 @@ func TestAccNetworkFirewallLoggingConfiguration_S3LogDestination_prefix(t *testi ), }, { - Config: testAccLoggingConfigurationConfig_s3UpdatePrefix(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3UpdatePrefix(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -339,7 +339,7 @@ func TestAccNetworkFirewallLoggingConfiguration_updateFirewallARN(t *testing.T) CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttrPair(resourceName, "firewall_arn", firewallResourceName, names.AttrARN), @@ -347,7 +347,7 @@ func TestAccNetworkFirewallLoggingConfiguration_updateFirewallARN(t *testing.T) }, { // ForceNew Firewall i.e. LoggingConfiguration Resource - Config: testAccLoggingConfigurationConfig_s3UpdateFirewallARN(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3UpdateFirewallARN(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttrPair(resourceName, "firewall_arn", firewallResourceName, names.AttrARN), @@ -377,39 +377,39 @@ func TestAccNetworkFirewallLoggingConfiguration_updateLogDestinationType(t *test CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, networkfirewall.LogDestinationTypeCloudWatchLogs, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.logGroup": logGroupName, - "log_destination_type": networkfirewall.LogDestinationTypeCloudWatchLogs, - "log_type": networkfirewall.LogTypeFlow, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), }), ), }, { - Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, networkfirewall.LogDestinationTypeKinesisDataFirehose, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_kinesis(streamName, rName, string(awstypes.LogDestinationTypeKinesisDataFirehose), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.deliveryStream": streamName, - "log_destination_type": networkfirewall.LogDestinationTypeKinesisDataFirehose, - "log_type": networkfirewall.LogTypeFlow, + "log_destination_type": string(awstypes.LogDestinationTypeKinesisDataFirehose), + "log_type": string(awstypes.LogTypeFlow), }), ), }, { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ - "log_destination_type": networkfirewall.LogDestinationTypeS3, - "log_type": networkfirewall.LogTypeFlow, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeFlow), }), ), }, @@ -436,13 +436,13 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToMultipleLogDestinations( CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeAlert), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeAlert)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), ), }, { - Config: testAccLoggingConfigurationConfig_s3AndKinesis(bucketName, streamName, rName, networkfirewall.LogTypeAlert, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3AndKinesis(bucketName, streamName, rName, string(awstypes.LogTypeAlert), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -450,19 +450,19 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToMultipleLogDestinations( resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.deliveryStream": streamName, - "log_destination_type": networkfirewall.LogDestinationTypeKinesisDataFirehose, - "log_type": networkfirewall.LogTypeFlow, + "log_destination_type": string(awstypes.LogDestinationTypeKinesisDataFirehose), + "log_type": string(awstypes.LogTypeFlow), }), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.bucketName": bucketName, - "log_destination_type": networkfirewall.LogDestinationTypeS3, - "log_type": networkfirewall.LogTypeAlert, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeAlert), }), ), }, { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeAlert), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeAlert)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -492,7 +492,7 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToSingleAlertTypeLogDestin CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3AndCloudWatch(bucketName, logGroupName, rName, networkfirewall.LogTypeAlert, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3AndCloudWatch(bucketName, logGroupName, rName, string(awstypes.LogTypeAlert), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -500,19 +500,19 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToSingleAlertTypeLogDestin resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.logGroup": logGroupName, - "log_destination_type": networkfirewall.LogDestinationTypeCloudWatchLogs, - "log_type": networkfirewall.LogTypeFlow, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), }), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.bucketName": bucketName, - "log_destination_type": networkfirewall.LogDestinationTypeS3, - "log_type": networkfirewall.LogTypeAlert, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeAlert), }), ), }, { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeAlert), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeAlert)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -520,8 +520,8 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToSingleAlertTypeLogDestin resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.bucketName": bucketName, - "log_destination_type": networkfirewall.LogDestinationTypeS3, - "log_type": networkfirewall.LogTypeAlert, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeAlert), }), ), }, @@ -548,7 +548,7 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToSingleFlowTypeLogDestina CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3AndCloudWatch(bucketName, logGroupName, rName, networkfirewall.LogTypeAlert, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3AndCloudWatch(bucketName, logGroupName, rName, string(awstypes.LogTypeAlert), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -556,19 +556,19 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToSingleFlowTypeLogDestina resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.logGroup": logGroupName, - "log_destination_type": networkfirewall.LogDestinationTypeCloudWatchLogs, - "log_type": networkfirewall.LogTypeFlow, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), }), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.bucketName": bucketName, - "log_destination_type": networkfirewall.LogDestinationTypeS3, - "log_type": networkfirewall.LogTypeAlert, + "log_destination_type": string(awstypes.LogDestinationTypeS3), + "log_type": string(awstypes.LogTypeAlert), }), ), }, { - Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, networkfirewall.LogDestinationTypeCloudWatchLogs, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, string(awstypes.LogDestinationTypeCloudwatchLogs), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "logging_configuration.#", acctest.Ct1), @@ -576,8 +576,8 @@ func TestAccNetworkFirewallLoggingConfiguration_updateToSingleFlowTypeLogDestina resource.TestCheckTypeSetElemNestedAttrs(resourceName, "logging_configuration.0.log_destination_config.*", map[string]string{ "log_destination.%": acctest.Ct1, "log_destination.logGroup": logGroupName, - "log_destination_type": networkfirewall.LogDestinationTypeCloudWatchLogs, - "log_type": networkfirewall.LogTypeFlow, + "log_destination_type": string(awstypes.LogDestinationTypeCloudwatchLogs), + "log_type": string(awstypes.LogTypeFlow), }), ), }, @@ -603,7 +603,7 @@ func TestAccNetworkFirewallLoggingConfiguration_disappears(t *testing.T) { CheckDestroy: testAccCheckLoggingConfigurationDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, networkfirewall.LogDestinationTypeS3, networkfirewall.LogTypeFlow), + Config: testAccLoggingConfigurationConfig_s3(bucketName, rName, string(awstypes.LogDestinationTypeS3), string(awstypes.LogTypeFlow)), Check: resource.ComposeTestCheckFunc( testAccCheckLoggingConfigurationExists(ctx, resourceName), acctest.CheckResourceDisappears(ctx, acctest.Provider, tfnetworkfirewall.ResourceLoggingConfiguration(), resourceName), @@ -621,17 +621,19 @@ func testAccCheckLoggingConfigurationDestroy(ctx context.Context) resource.TestC continue } - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) - output, err := tfnetworkfirewall.FindLoggingConfiguration(ctx, conn, rs.Primary.ID) - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) + + _, err := tfnetworkfirewall.FindLoggingConfigurationByARN(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { continue } + if err != nil { return err } - if output != nil { - return fmt.Errorf("NetworkFirewall Logging Configuration for firewall (%s) still exists", rs.Primary.ID) - } + + return fmt.Errorf("NetworkFirewall Logging Configuration %s still exists", rs.Primary.ID) } return nil @@ -645,54 +647,19 @@ func testAccCheckLoggingConfigurationExists(ctx context.Context, n string) resou return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No NetworkFirewall Logging Configuration ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) - output, err := tfnetworkfirewall.FindLoggingConfiguration(ctx, conn, rs.Primary.ID) - if err != nil { - return err - } - if output == nil || output.LoggingConfiguration == nil { - return fmt.Errorf("NetworkFirewall Logging Configuration for firewall (%s) not found", rs.Primary.ID) - } + _, err := tfnetworkfirewall.FindLoggingConfigurationByARN(ctx, conn, rs.Primary.ID) - return nil + return err } } -func testAccLoggingConfigurationBaseConfig(rName string) string { - return fmt.Sprintf(` -data "aws_availability_zones" "available" { - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - -resource "aws_vpc" "test" { - cidr_block = "192.168.0.0/16" - - tags = { - Name = %[1]q - } -} - -resource "aws_subnet" "test" { - availability_zone = data.aws_availability_zones.available.names[0] - cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, 0) - vpc_id = aws_vpc.test.id - - tags = { - Name = %[1]q - } -} - +func testAccLoggingConfigurationConfig_base(rName string) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` resource "aws_networkfirewall_firewall_policy" "test" { name = %[1]q + firewall_policy { stateless_fragment_default_actions = ["aws:drop"] stateless_default_actions = ["aws:pass"] @@ -705,43 +672,17 @@ resource "aws_networkfirewall_firewall" "test" { vpc_id = aws_vpc.test.id subnet_mapping { - subnet_id = aws_subnet.test.id - } -} -`, rName) -} - -func testAccLoggingConfigurationBaseConfig_updateFirewall(rName string) string { - return fmt.Sprintf(` -data "aws_availability_zones" "available" { - state = "available" - - filter { - name = "opt-in-status" - values = ["opt-in-not-required"] - } -} - -resource "aws_vpc" "test" { - cidr_block = "192.168.0.0/16" - - tags = { - Name = %[1]q + subnet_id = aws_subnet.test[0].id } } - -resource "aws_subnet" "test" { - availability_zone = data.aws_availability_zones.available.names[0] - cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, 0) - vpc_id = aws_vpc.test.id - - tags = { - Name = %[1]q - } +`, rName)) } +func testAccLoggingConfigurationConfig_baseFirewallUpdated(rName string) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` resource "aws_networkfirewall_firewall_policy" "test" { name = %[1]q + firewall_policy { stateless_fragment_default_actions = ["aws:drop"] stateless_default_actions = ["aws:pass"] @@ -754,16 +695,16 @@ resource "aws_networkfirewall_firewall" "test" { vpc_id = aws_vpc.test.id subnet_mapping { - subnet_id = aws_subnet.test.id + subnet_id = aws_subnet.test[0].id } } -`, rName) +`, rName)) } -func testAccLoggingConfigurationS3BucketDependencyConfig(rName string) string { +func testAccLoggingConfigurationConfig_baseS3Bucket(rName string) string { return fmt.Sprintf(` resource "aws_s3_bucket" "test" { - bucket = %q + bucket = %[1]q force_destroy = true lifecycle { @@ -773,10 +714,10 @@ resource "aws_s3_bucket" "test" { `, rName) } -func testAccLoggingConfigurationCloudWatchDependencyConfig(rName string) string { +func testAccLoggingConfigurationConfig_baseCloudWatch(rName string) string { return fmt.Sprintf(` resource "aws_cloudwatch_log_group" "test" { - name = %q + name = %[1]q lifecycle { create_before_destroy = true @@ -785,7 +726,7 @@ resource "aws_cloudwatch_log_group" "test" { `, rName) } -func testAccLoggingConfiguration_kinesisDependenciesConfig(rName, streamName string) string { +func testAccLoggingConfigurationConfig_baseFirehose(rName, streamName string) string { return fmt.Sprintf(` data "aws_caller_identity" "current" {} @@ -887,8 +828,8 @@ resource "aws_kinesis_firehose_delivery_stream" "test" { func testAccLoggingConfigurationConfig_s3(bucketName, rName, destinationType, logType string) string { return acctest.ConfigCompose( - testAccLoggingConfigurationBaseConfig(rName), - testAccLoggingConfigurationS3BucketDependencyConfig(bucketName), + testAccLoggingConfigurationConfig_base(rName), + testAccLoggingConfigurationConfig_baseS3Bucket(bucketName), fmt.Sprintf(` resource "aws_networkfirewall_logging_configuration" "test" { firewall_arn = aws_networkfirewall_firewall.test.arn @@ -908,8 +849,8 @@ resource "aws_networkfirewall_logging_configuration" "test" { func testAccLoggingConfigurationConfig_s3UpdateFirewallARN(bucketName, rName, destinationType, logType string) string { return acctest.ConfigCompose( - testAccLoggingConfigurationBaseConfig_updateFirewall(rName), - testAccLoggingConfigurationS3BucketDependencyConfig(bucketName), + testAccLoggingConfigurationConfig_baseFirewallUpdated(rName), + testAccLoggingConfigurationConfig_baseS3Bucket(bucketName), fmt.Sprintf(` resource "aws_networkfirewall_logging_configuration" "test" { firewall_arn = aws_networkfirewall_firewall.test.arn @@ -929,8 +870,8 @@ resource "aws_networkfirewall_logging_configuration" "test" { func testAccLoggingConfigurationConfig_s3UpdatePrefix(bucketName, rName, destinationType, logType string) string { return acctest.ConfigCompose( - testAccLoggingConfigurationBaseConfig(rName), - testAccLoggingConfigurationS3BucketDependencyConfig(bucketName), + testAccLoggingConfigurationConfig_base(rName), + testAccLoggingConfigurationConfig_baseS3Bucket(bucketName), fmt.Sprintf(` resource "aws_networkfirewall_logging_configuration" "test" { firewall_arn = aws_networkfirewall_firewall.test.arn @@ -951,8 +892,8 @@ resource "aws_networkfirewall_logging_configuration" "test" { func testAccLoggingConfigurationConfig_kinesis(streamName, rName, destinationType, logType string) string { return acctest.ConfigCompose( - testAccLoggingConfigurationBaseConfig(rName), - testAccLoggingConfiguration_kinesisDependenciesConfig(rName, streamName), + testAccLoggingConfigurationConfig_base(rName), + testAccLoggingConfigurationConfig_baseFirehose(rName, streamName), fmt.Sprintf(` resource "aws_networkfirewall_logging_configuration" "test" { firewall_arn = aws_networkfirewall_firewall.test.arn @@ -972,8 +913,8 @@ resource "aws_networkfirewall_logging_configuration" "test" { func testAccLoggingConfigurationConfig_cloudWatch(logGroupName, rName, destinationType, logType string) string { return acctest.ConfigCompose( - testAccLoggingConfigurationBaseConfig(rName), - testAccLoggingConfigurationCloudWatchDependencyConfig(logGroupName), + testAccLoggingConfigurationConfig_base(rName), + testAccLoggingConfigurationConfig_baseCloudWatch(logGroupName), fmt.Sprintf(` resource "aws_networkfirewall_logging_configuration" "test" { firewall_arn = aws_networkfirewall_firewall.test.arn @@ -993,9 +934,9 @@ resource "aws_networkfirewall_logging_configuration" "test" { func testAccLoggingConfigurationConfig_s3AndKinesis(bucketName, streamName, rName, logTypeS3, logTypeKinesis string) string { return acctest.ConfigCompose( - testAccLoggingConfigurationS3BucketDependencyConfig(bucketName), - testAccLoggingConfiguration_kinesisDependenciesConfig(rName, streamName), - testAccLoggingConfigurationBaseConfig(rName), + testAccLoggingConfigurationConfig_baseS3Bucket(bucketName), + testAccLoggingConfigurationConfig_baseFirehose(rName, streamName), + testAccLoggingConfigurationConfig_base(rName), fmt.Sprintf(` resource "aws_networkfirewall_logging_configuration" "test" { firewall_arn = aws_networkfirewall_firewall.test.arn @@ -1023,9 +964,9 @@ resource "aws_networkfirewall_logging_configuration" "test" { func testAccLoggingConfigurationConfig_s3AndCloudWatch(bucketName, logGroupName, rName, logTypeS3, logTypeCloudWatch string) string { return acctest.ConfigCompose( - testAccLoggingConfigurationBaseConfig(rName), - testAccLoggingConfigurationS3BucketDependencyConfig(bucketName), - testAccLoggingConfigurationCloudWatchDependencyConfig(logGroupName), + testAccLoggingConfigurationConfig_base(rName), + testAccLoggingConfigurationConfig_baseS3Bucket(bucketName), + testAccLoggingConfigurationConfig_baseCloudWatch(logGroupName), fmt.Sprintf(` resource "aws_networkfirewall_logging_configuration" "test" { firewall_arn = aws_networkfirewall_firewall.test.arn diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 90a2a182547..2d05813051a 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -67,8 +67,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceLoggingConfiguration, + Factory: resourceLoggingConfiguration, TypeName: "aws_networkfirewall_logging_configuration", + Name: "Logging Configuration", }, { Factory: ResourceResourcePolicy, From 1e5eb2935328518388ca21c854fb41a59df065eb Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 10:04:22 -0400 Subject: [PATCH 54/68] r/aws_networkfirewall_resource_policy: Migrate to AWS SDK for Go v2. --- .../service/networkfirewall/exports_test.go | 2 + internal/service/networkfirewall/find.go | 17 --- .../firewall_resource_policy_data_source.go | 2 +- .../networkfirewall/resource_policy.go | 104 ++++++++++-------- .../networkfirewall/resource_policy_test.go | 52 ++++----- .../networkfirewall/service_package_gen.go | 3 +- 6 files changed, 86 insertions(+), 94 deletions(-) diff --git a/internal/service/networkfirewall/exports_test.go b/internal/service/networkfirewall/exports_test.go index 5d4fc7059fc..84cbcd30712 100644 --- a/internal/service/networkfirewall/exports_test.go +++ b/internal/service/networkfirewall/exports_test.go @@ -6,8 +6,10 @@ package networkfirewall // Exports for use in tests only. var ( ResourceLoggingConfiguration = resourceLoggingConfiguration + ResourceResourcePolicy = resourceResourcePolicy ResourceTLSInspectionConfiguration = newTLSInspectionConfigurationResource FindLoggingConfigurationByARN = findLoggingConfigurationByARN + FindResourcePolicyByARN = findResourcePolicyByARN FindTLSInspectionConfigurationByARN = findTLSInspectionConfigurationByARN ) diff --git a/internal/service/networkfirewall/find.go b/internal/service/networkfirewall/find.go index aafe1476376..98154f36253 100644 --- a/internal/service/networkfirewall/find.go +++ b/internal/service/networkfirewall/find.go @@ -27,20 +27,3 @@ func FindFirewallPolicyByNameAndARN(ctx context.Context, conn *networkfirewall.N } return output, nil } - -// FindResourcePolicy returns the Policy string from a call to DescribeResourcePolicyWithContext -// given the context and resource ARN. -// Returns nil if the FindResourcePolicy is not found. -func FindResourcePolicy(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*string, error) { - input := &networkfirewall.DescribeResourcePolicyInput{ - ResourceArn: aws.String(arn), - } - output, err := conn.DescribeResourcePolicyWithContext(ctx, input) - if err != nil { - return nil, err - } - if output == nil { - return nil, nil - } - return output.Policy, nil -} diff --git a/internal/service/networkfirewall/firewall_resource_policy_data_source.go b/internal/service/networkfirewall/firewall_resource_policy_data_source.go index d7036ac5cff..d76cdc18c0d 100644 --- a/internal/service/networkfirewall/firewall_resource_policy_data_source.go +++ b/internal/service/networkfirewall/firewall_resource_policy_data_source.go @@ -40,7 +40,7 @@ func dataSourceFirewallResourcePolicyRead(ctx context.Context, d *schema.Resourc conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) resourceARN := d.Get(names.AttrResourceARN).(string) - policy, err := FindResourcePolicy(ctx, conn, resourceARN) + policy, err := FindResourcePolicyByARN(ctx, conn, resourceARN) if err != nil { return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Resource Policy (%s): %s", resourceARN, err) diff --git a/internal/service/networkfirewall/resource_policy.go b/internal/service/networkfirewall/resource_policy.go index 69799e4bf99..b9d8f99fcda 100644 --- a/internal/service/networkfirewall/resource_policy.go +++ b/internal/service/networkfirewall/resource_policy.go @@ -8,22 +8,24 @@ import ( "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) -// @SDKResource("aws_networkfirewall_resource_policy") -func ResourceResourcePolicy() *schema.Resource { +// @SDKResource("aws_networkfirewall_resource_policy", name="Resource Policy") +func resourceResourcePolicy() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceResourcePolicyPut, ReadWithoutTimeout: resourceResourcePolicyRead, @@ -36,10 +38,11 @@ func ResourceResourcePolicy() *schema.Resource { Schema: map[string]*schema.Schema{ names.AttrPolicy: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringIsJSON, - DiffSuppressFunc: verify.SuppressEquivalentPolicyDiffs, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsJSON, + DiffSuppressFunc: verify.SuppressEquivalentPolicyDiffs, + DiffSuppressOnRefresh: true, StateFunc: func(v interface{}) string { json, _ := structure.NormalizeJsonString(v) return json @@ -57,84 +60,74 @@ func ResourceResourcePolicy() *schema.Resource { func resourceResourcePolicyPut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - resourceArn := d.Get(names.AttrResourceARN).(string) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) policy, err := structure.NormalizeJsonString(d.Get(names.AttrPolicy).(string)) - if err != nil { - return sdkdiag.AppendErrorf(diags, "policy (%s) is invalid JSON: %s", policy, err) + return sdkdiag.AppendFromErr(diags, err) } + resourceARN := d.Get(names.AttrResourceARN).(string) input := &networkfirewall.PutResourcePolicyInput{ - ResourceArn: aws.String(resourceArn), Policy: aws.String(policy), + ResourceArn: aws.String(resourceARN), } - log.Printf("[DEBUG] Putting NetworkFirewall Resource Policy for resource: %s", resourceArn) + _, err = conn.PutResourcePolicy(ctx, input) - _, err = conn.PutResourcePolicyWithContext(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "putting NetworkFirewall Resource Policy (for resource: %s): %s", resourceArn, err) + return sdkdiag.AppendErrorf(diags, "putting NetworkFirewall Resource Policy (%s): %s", resourceARN, err) } - d.SetId(resourceArn) + if d.IsNewResource() { + d.SetId(resourceARN) + } return append(diags, resourceResourcePolicyRead(ctx, d, meta)...) } func resourceResourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - resourceArn := d.Id() + policy, err := findResourcePolicyByARN(ctx, conn, d.Id()) - log.Printf("[DEBUG] Reading NetworkFirewall Resource Policy for resource: %s", resourceArn) - - policy, err := FindResourcePolicy(ctx, conn, resourceArn) - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { - log.Printf("[WARN] NetworkFirewall Resource Policy (for resource: %s) not found, removing from state", resourceArn) + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] NetworkFirewall Resource Policy (%s) not found, removing from state", d.Id()) d.SetId("") return diags } - if err != nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Resource Policy (for resource: %s): %s", resourceArn, err) - } - if policy == nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Resource Policy (for resource: %s): empty output", resourceArn) + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Resource Policy (%s): %s", d.Id(), err) } - d.Set(names.AttrResourceARN, resourceArn) - - policyToSet, err := verify.PolicyToSet(d.Get(names.AttrPolicy).(string), aws.StringValue(policy)) - + policyToSet, err := verify.PolicyToSet(d.Get(names.AttrPolicy).(string), aws.ToString(policy)) if err != nil { - return sdkdiag.AppendErrorf(diags, "setting policy %s: %s", aws.StringValue(policy), err) + return sdkdiag.AppendFromErr(diags, err) } d.Set(names.AttrPolicy, policyToSet) + d.Set(names.AttrResourceARN, d.Id()) return diags } func resourceResourcePolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) + log.Printf("[DEBUG] Deleting NetworkFirewall Resource Policy: %s", d.Id()) const ( timeout = 2 * time.Minute ) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - - log.Printf("[DEBUG] Deleting NetworkFirewall Resource Policy: %s", d.Id()) - _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, timeout, func() (interface{}, error) { - return conn.DeleteResourcePolicyWithContext(ctx, &networkfirewall.DeleteResourcePolicyInput{ + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.InvalidResourcePolicyException](ctx, timeout, func() (interface{}, error) { + return conn.DeleteResourcePolicy(ctx, &networkfirewall.DeleteResourcePolicyInput{ ResourceArn: aws.String(d.Id()), }) - }, networkfirewall.ErrCodeInvalidResourcePolicyException, "The supplied policy does not match RAM managed permissions") + }, "The supplied policy does not match RAM managed permissions") - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -144,3 +137,28 @@ func resourceResourcePolicyDelete(ctx context.Context, d *schema.ResourceData, m return diags } + +func findResourcePolicyByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*string, error) { + input := &networkfirewall.DescribeResourcePolicyInput{ + ResourceArn: aws.String(arn), + } + + output, err := conn.DescribeResourcePolicy(ctx, input) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.Policy == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.Policy, nil +} diff --git a/internal/service/networkfirewall/resource_policy_test.go b/internal/service/networkfirewall/resource_policy_test.go index cefb310bacf..09721d48099 100644 --- a/internal/service/networkfirewall/resource_policy_test.go +++ b/internal/service/networkfirewall/resource_policy_test.go @@ -9,14 +9,13 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" tfnetworkfirewall "github.com/hashicorp/terraform-provider-aws/internal/service/networkfirewall" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -200,17 +199,19 @@ func testAccCheckResourcePolicyDestroy(ctx context.Context) resource.TestCheckFu continue } - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) - policy, err := tfnetworkfirewall.FindResourcePolicy(ctx, conn, rs.Primary.ID) - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) + + _, err := tfnetworkfirewall.FindResourcePolicyByARN(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { continue } + if err != nil { return err } - if policy != nil { - return fmt.Errorf("NetworkFirewall Resource Policy (for resource: %s) still exists", rs.Primary.ID) - } + + return fmt.Errorf("NetworkFirewall Resource Policy %s still exists", rs.Primary.ID) } return nil @@ -224,25 +225,15 @@ func testAccCheckResourcePolicyExists(ctx context.Context, n string) resource.Te return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No NetworkFirewall Resource Policy ID is set") - } + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) - policy, err := tfnetworkfirewall.FindResourcePolicy(ctx, conn, rs.Primary.ID) - if err != nil { - return err - } - - if policy == nil { - return fmt.Errorf("NetworkFirewall Resource Policy (for resource: %s) not found", rs.Primary.ID) - } + _, err := tfnetworkfirewall.FindResourcePolicyByARN(ctx, conn, rs.Primary.ID) - return nil + return err } } -func testAccResourcePolicyFirewallPolicyBaseConfig(rName string) string { +func testAccResourcePolicyFirewallPolicyConfig_base(rName string) string { return fmt.Sprintf(` data "aws_partition" "current" {} @@ -250,6 +241,7 @@ data "aws_caller_identity" "current" {} resource "aws_networkfirewall_firewall_policy" "test" { name = %[1]q + firewall_policy { stateless_fragment_default_actions = ["aws:drop"] stateless_default_actions = ["aws:pass"] @@ -259,8 +251,7 @@ resource "aws_networkfirewall_firewall_policy" "test" { } func testAccResourcePolicyConfig_basic(rName string) string { - return acctest.ConfigCompose( - testAccResourcePolicyFirewallPolicyBaseConfig(rName), ` + return acctest.ConfigCompose(testAccResourcePolicyFirewallPolicyConfig_base(rName), ` resource "aws_networkfirewall_resource_policy" "test" { resource_arn = aws_networkfirewall_firewall_policy.test.arn # policy's Action element must include all of the following operations @@ -285,8 +276,7 @@ resource "aws_networkfirewall_resource_policy" "test" { } func testAccResourcePolicyConfig_equivalent(rName string) string { - return acctest.ConfigCompose( - testAccResourcePolicyFirewallPolicyBaseConfig(rName), ` + return acctest.ConfigCompose(testAccResourcePolicyFirewallPolicyConfig_base(rName), ` resource "aws_networkfirewall_resource_policy" "test" { resource_arn = aws_networkfirewall_firewall_policy.test.arn # policy's Action element must include all of the following operations @@ -310,7 +300,7 @@ resource "aws_networkfirewall_resource_policy" "test" { `) } -func testAccResourcePolicyRuleGroupBaseConfig(rName string) string { +func testAccResourcePolicyConfig_baseRuleGroup(rName string) string { return fmt.Sprintf(` data "aws_partition" "current" {} @@ -318,7 +308,7 @@ data "aws_caller_identity" "current" {} resource "aws_networkfirewall_rule_group" "test" { capacity = 100 - name = %q + name = %[1]q type = "STATEFUL" rule_group { rules_source { @@ -334,8 +324,7 @@ resource "aws_networkfirewall_rule_group" "test" { } func testAccResourcePolicyConfig_ruleGroup(rName string) string { - return acctest.ConfigCompose( - testAccResourcePolicyRuleGroupBaseConfig(rName), ` + return acctest.ConfigCompose(testAccResourcePolicyConfig_baseRuleGroup(rName), ` resource "aws_networkfirewall_resource_policy" "test" { resource_arn = aws_networkfirewall_rule_group.test.arn # policy's Action element must include all of the following operations @@ -359,8 +348,7 @@ resource "aws_networkfirewall_resource_policy" "test" { } func testAccResourcePolicyConfig_ruleGroupUpdate(rName string) string { - return acctest.ConfigCompose( - testAccResourcePolicyRuleGroupBaseConfig(rName), ` + return acctest.ConfigCompose(testAccResourcePolicyConfig_baseRuleGroup(rName), ` resource "aws_networkfirewall_resource_policy" "test" { resource_arn = aws_networkfirewall_rule_group.test.arn # policy's Action element must include all of the following operations diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 2d05813051a..d3441b91141 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -72,8 +72,9 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka Name: "Logging Configuration", }, { - Factory: ResourceResourcePolicy, + Factory: resourceResourcePolicy, TypeName: "aws_networkfirewall_resource_policy", + Name: "Resource Policy", }, { Factory: ResourceRuleGroup, From 245f6219c75262ce637662ecdcf735f1f5981973 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 10:07:19 -0400 Subject: [PATCH 55/68] d/aws_networkfirewall_resource_policy: Correct source file names. --- ...ource_policy_data_source.go => resource_policy_data_source.go} | 0 ...cy_data_source_test.go => resource_policy_data_source_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename internal/service/networkfirewall/{firewall_resource_policy_data_source.go => resource_policy_data_source.go} (100%) rename internal/service/networkfirewall/{firewall_resource_policy_data_source_test.go => resource_policy_data_source_test.go} (100%) diff --git a/internal/service/networkfirewall/firewall_resource_policy_data_source.go b/internal/service/networkfirewall/resource_policy_data_source.go similarity index 100% rename from internal/service/networkfirewall/firewall_resource_policy_data_source.go rename to internal/service/networkfirewall/resource_policy_data_source.go diff --git a/internal/service/networkfirewall/firewall_resource_policy_data_source_test.go b/internal/service/networkfirewall/resource_policy_data_source_test.go similarity index 100% rename from internal/service/networkfirewall/firewall_resource_policy_data_source_test.go rename to internal/service/networkfirewall/resource_policy_data_source_test.go From fae48ce1439dd97cd69830f84c47a272abde9914 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 10:09:27 -0400 Subject: [PATCH 56/68] d/aws_networkfirewall_resource_policy: Migrate to AWS SDK for Go v2. --- .../resource_policy_data_source.go | 18 ++++++------------ .../resource_policy_data_source_test.go | 2 +- .../networkfirewall/service_package_gen.go | 3 ++- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/internal/service/networkfirewall/resource_policy_data_source.go b/internal/service/networkfirewall/resource_policy_data_source.go index d76cdc18c0d..287526effc5 100644 --- a/internal/service/networkfirewall/resource_policy_data_source.go +++ b/internal/service/networkfirewall/resource_policy_data_source.go @@ -14,10 +14,10 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -// @SDKDataSource("aws_networkfirewall_resource_policy") -func DataSourceFirewallResourcePolicy() *schema.Resource { +// @SDKDataSource("aws_networkfirewall_resource_policy", name="Resource Policy") +func dataSourceResourcePolicy() *schema.Resource { return &schema.Resource{ - ReadWithoutTimeout: dataSourceFirewallResourcePolicyRead, + ReadWithoutTimeout: dataSourceResourcePolicyRead, Schema: map[string]*schema.Schema{ names.AttrPolicy: { @@ -27,29 +27,23 @@ func DataSourceFirewallResourcePolicy() *schema.Resource { names.AttrResourceARN: { Type: schema.TypeString, Required: true, - ForceNew: true, ValidateFunc: verify.ValidARN, }, }, } } -func dataSourceFirewallResourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func dataSourceResourcePolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) resourceARN := d.Get(names.AttrResourceARN).(string) - policy, err := FindResourcePolicyByARN(ctx, conn, resourceARN) + policy, err := findResourcePolicyByARN(ctx, conn, resourceARN) if err != nil { return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Resource Policy (%s): %s", resourceARN, err) } - if policy == nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Resource Policy (%s): empty output", resourceARN) - } - d.SetId(resourceARN) d.Set(names.AttrPolicy, policy) d.Set(names.AttrResourceARN, resourceARN) diff --git a/internal/service/networkfirewall/resource_policy_data_source_test.go b/internal/service/networkfirewall/resource_policy_data_source_test.go index d086fdd63c7..22206eaf0b1 100644 --- a/internal/service/networkfirewall/resource_policy_data_source_test.go +++ b/internal/service/networkfirewall/resource_policy_data_source_test.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -func TestAccNetworkFirewallFirewallResourcePolicyDataSource_basic(t *testing.T) { +func TestAccNetworkFirewallResourcePolicyDataSource_basic(t *testing.T) { ctx := acctest.Context(t) rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_resource_policy.test" diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index d3441b91141..bceb430bf92 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -42,8 +42,9 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac TypeName: "aws_networkfirewall_firewall_policy", }, { - Factory: DataSourceFirewallResourcePolicy, + Factory: dataSourceResourcePolicy, TypeName: "aws_networkfirewall_resource_policy", + Name: "Resource Policy", }, } } From 107bf880505403670a61b4e4fb11985b8e2537d8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 10:49:21 -0400 Subject: [PATCH 57/68] r/aws_networkfirewall_firewall_policy: Migrate to AWS SDK for Go v2. --- .../service/networkfirewall/exports_test.go | 2 + .../networkfirewall/firewall_policy.go | 599 +++++++++--------- .../networkfirewall/firewall_policy_test.go | 39 +- internal/service/networkfirewall/helpers.go | 267 ++++---- .../service/networkfirewall/rule_group.go | 56 -- .../networkfirewall/service_package_gen.go | 2 +- 6 files changed, 483 insertions(+), 482 deletions(-) diff --git a/internal/service/networkfirewall/exports_test.go b/internal/service/networkfirewall/exports_test.go index 84cbcd30712..16b39e3785c 100644 --- a/internal/service/networkfirewall/exports_test.go +++ b/internal/service/networkfirewall/exports_test.go @@ -5,10 +5,12 @@ package networkfirewall // Exports for use in tests only. var ( + ResourceFirewallPolicy = resourceFirewallPolicy ResourceLoggingConfiguration = resourceLoggingConfiguration ResourceResourcePolicy = resourceResourcePolicy ResourceTLSInspectionConfiguration = newTLSInspectionConfigurationResource + FindFirewallPolicyByARN = findFirewallPolicyByARN FindLoggingConfigurationByARN = findLoggingConfigurationByARN FindResourcePolicyByARN = findResourcePolicyByARN FindTLSInspectionConfigurationByARN = findTLSInspectionConfigurationByARN diff --git a/internal/service/networkfirewall/firewall_policy.go b/internal/service/networkfirewall/firewall_policy.go index 20add02b7ff..b560b4ad07a 100644 --- a/internal/service/networkfirewall/firewall_policy.go +++ b/internal/service/networkfirewall/firewall_policy.go @@ -9,15 +9,17 @@ import ( "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "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/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -28,7 +30,7 @@ import ( // @SDKResource("aws_networkfirewall_firewall_policy", name="Firewall Policy") // @Tags(identifierAttribute="id") -func ResourceFirewallPolicy() *schema.Resource { +func resourceFirewallPolicy() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceFirewallPolicyCreate, ReadWithoutTimeout: resourceFirewallPolicyRead, @@ -39,166 +41,168 @@ func ResourceFirewallPolicy() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, - Schema: map[string]*schema.Schema{ - names.AttrARN: { - Type: schema.TypeString, - Computed: true, - }, - names.AttrDescription: { - Type: schema.TypeString, - Optional: true, - }, - names.AttrEncryptionConfiguration: encryptionConfigurationSchema(), - "firewall_policy": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "policy_variables": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "rule_variables": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrKey: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 32), - validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), - validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), - ), - }, - "ip_set": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "definition": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + SchemaFunc: func() map[string]*schema.Schema { + return map[string]*schema.Schema{ + names.AttrARN: { + Type: schema.TypeString, + Computed: true, + }, + names.AttrDescription: { + Type: schema.TypeString, + Optional: true, + }, + names.AttrEncryptionConfiguration: encryptionConfigurationSchema(), + "firewall_policy": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "policy_variables": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rule_variables": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_set": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "definition": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, }, }, + names.AttrKey: { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 32), + validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), + validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), + ), + }, }, }, }, }, }, }, - }, - "stateful_default_actions": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "stateful_engine_options": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "rule_order": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice(networkfirewall.RuleOrder_Values(), false), - }, - "stream_exception_policy": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice(networkfirewall.StreamExceptionPolicy_Values(), false), + "stateful_default_actions": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "stateful_engine_options": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rule_order": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.RuleOrder](), + }, + "stream_exception_policy": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.StreamExceptionPolicy](), + }, }, }, }, - }, - "stateful_rule_group_reference": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "override": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrAction: { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice(networkfirewall.OverrideAction_Values(), false), + "stateful_rule_group_reference": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "override": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrAction: { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: enum.Validate[awstypes.OverrideAction](), + }, }, }, }, - }, - names.AttrPriority: { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntAtLeast(1), - }, - names.AttrResourceARN: { - Type: schema.TypeString, - Required: true, - ValidateFunc: verify.ValidARN, + names.AttrPriority: { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(1), + }, + names.AttrResourceARN: { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, }, }, }, - }, - "stateless_custom_action": customActionSchema(), - "stateless_default_actions": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "stateless_fragment_default_actions": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "stateless_rule_group_reference": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrPriority: { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntAtLeast(1), - }, - names.AttrResourceARN: { - Type: schema.TypeString, - Required: true, - ValidateFunc: verify.ValidARN, + "stateless_custom_action": customActionSchema(), + "stateless_default_actions": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "stateless_fragment_default_actions": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "stateless_rule_group_reference": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrPriority: { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntAtLeast(1), + }, + names.AttrResourceARN: { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, }, }, }, - }, - "tls_inspection_configuration_arn": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: verify.ValidARN, + "tls_inspection_configuration_arn": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidARN, + }, }, }, }, - }, - names.AttrName: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - names.AttrTags: tftags.TagsSchema(), - names.AttrTagsAll: tftags.TagsSchemaComputed(), - "update_token": { - Type: schema.TypeString, - Computed: true, - }, + names.AttrName: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), + "update_token": { + Type: schema.TypeString, + Computed: true, + }, + } }, CustomizeDiff: customdiff.Sequence( @@ -214,8 +218,7 @@ func ResourceFirewallPolicy() *schema.Resource { func resourceFirewallPolicyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) name := d.Get(names.AttrName).(string) input := &networkfirewall.CreateFirewallPolicyInput{ @@ -227,27 +230,27 @@ func resourceFirewallPolicyCreate(ctx context.Context, d *schema.ResourceData, m if v, ok := d.GetOk(names.AttrDescription); ok { input.Description = aws.String(v.(string)) } + if v, ok := d.GetOk(names.AttrEncryptionConfiguration); ok { input.EncryptionConfiguration = expandEncryptionConfiguration(v.([]interface{})) } - output, err := conn.CreateFirewallPolicyWithContext(ctx, input) + output, err := conn.CreateFirewallPolicy(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating NetworkFirewall Firewall Policy (%s): %s", name, err) } - d.SetId(aws.StringValue(output.FirewallPolicyResponse.FirewallPolicyArn)) + d.SetId(aws.ToString(output.FirewallPolicyResponse.FirewallPolicyArn)) return append(diags, resourceFirewallPolicyRead(ctx, d, meta)...) } func resourceFirewallPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - - output, err := FindFirewallPolicyByARN(ctx, conn, d.Id()) + output, err := findFirewallPolicyByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] NetworkFirewall Firewall Policy (%s) not found, removing from state", d.Id()) @@ -262,7 +265,9 @@ func resourceFirewallPolicyRead(ctx context.Context, d *schema.ResourceData, met response := output.FirewallPolicyResponse d.Set(names.AttrARN, response.FirewallPolicyArn) d.Set(names.AttrDescription, response.Description) - d.Set(names.AttrEncryptionConfiguration, flattenEncryptionConfiguration(response.EncryptionConfiguration)) + if err := d.Set(names.AttrEncryptionConfiguration, flattenEncryptionConfiguration(response.EncryptionConfiguration)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting encryption_configuration: %s", err) + } if err := d.Set("firewall_policy", flattenFirewallPolicy(output.FirewallPolicy)); err != nil { return sdkdiag.AppendErrorf(diags, "setting firewall_policy: %s", err) } @@ -276,8 +281,7 @@ func resourceFirewallPolicyRead(ctx context.Context, d *schema.ResourceData, met func resourceFirewallPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) if d.HasChanges(names.AttrDescription, names.AttrEncryptionConfiguration, "firewall_policy") { input := &networkfirewall.UpdateFirewallPolicyInput{ @@ -287,12 +291,12 @@ func resourceFirewallPolicyUpdate(ctx context.Context, d *schema.ResourceData, m UpdateToken: aws.String(d.Get("update_token").(string)), } - // Only pass non-empty description values, else API request returns an InternalServiceError + // Only pass non-empty description values, else API request returns an InternalServiceError. if v, ok := d.GetOk(names.AttrDescription); ok { input.Description = aws.String(v.(string)) } - _, err := conn.UpdateFirewallPolicyWithContext(ctx, input) + _, err := conn.UpdateFirewallPolicy(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall Policy (%s): %s", d.Id(), err) @@ -304,20 +308,19 @@ func resourceFirewallPolicyUpdate(ctx context.Context, d *schema.ResourceData, m func resourceFirewallPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) + log.Printf("[DEBUG] Deleting NetworkFirewall Firewall Policy: %s", d.Id()) const ( timeout = 10 * time.Minute ) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - - log.Printf("[DEBUG] Deleting NetworkFirewall Firewall Policy: %s", d.Id()) - _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, timeout, func() (interface{}, error) { - return conn.DeleteFirewallPolicyWithContext(ctx, &networkfirewall.DeleteFirewallPolicyInput{ + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.InvalidOperationException](ctx, timeout, func() (interface{}, error) { + return conn.DeleteFirewallPolicy(ctx, &networkfirewall.DeleteFirewallPolicyInput{ FirewallPolicyArn: aws.String(d.Id()), }) - }, networkfirewall.ErrCodeInvalidOperationException, "Unable to delete the object because it is still in use") + }, "Unable to delete the object because it is still in use") - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -332,14 +335,14 @@ func resourceFirewallPolicyDelete(ctx context.Context, d *schema.ResourceData, m return diags } -func FindFirewallPolicyByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeFirewallPolicyOutput, error) { +func findFirewallPolicyByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeFirewallPolicyOutput, error) { input := &networkfirewall.DescribeFirewallPolicyInput{ FirewallPolicyArn: aws.String(arn), } - output, err := conn.DescribeFirewallPolicyWithContext(ctx, input) + output, err := conn.DescribeFirewallPolicy(ctx, input) - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -357,9 +360,9 @@ func FindFirewallPolicyByARN(ctx context.Context, conn *networkfirewall.NetworkF return output, nil } -func statusFirewallPolicy(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { +func statusFirewallPolicy(ctx context.Context, conn *networkfirewall.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - output, err := FindFirewallPolicyByARN(ctx, conn, arn) + output, err := findFirewallPolicyByARN(ctx, conn, arn) if tfresource.NotFound(err) { return nil, "", nil @@ -369,13 +372,13 @@ func statusFirewallPolicy(ctx context.Context, conn *networkfirewall.NetworkFire return nil, "", err } - return output, aws.StringValue(output.FirewallPolicyResponse.FirewallPolicyStatus), nil + return output, string(output.FirewallPolicyResponse.FirewallPolicyStatus), nil } } -func waitFirewallPolicyDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.DescribeFirewallPolicyOutput, error) { +func waitFirewallPolicyDeleted(ctx context.Context, conn *networkfirewall.Client, arn string, timeout time.Duration) (*networkfirewall.DescribeFirewallPolicyOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{networkfirewall.ResourceStatusDeleting}, + Pending: enum.Slice(awstypes.ResourceStatusDeleting), Target: []string{}, Refresh: statusFirewallPolicy(ctx, conn, arn), Timeout: timeout, @@ -390,248 +393,262 @@ func waitFirewallPolicyDeleted(ctx context.Context, conn *networkfirewall.Networ return nil, err } -func expandPolicyVariables(tfMap map[string]interface{}) *networkfirewall.PolicyVariables { +func expandPolicyVariables(tfMap map[string]interface{}) *awstypes.PolicyVariables { if tfMap == nil { return nil } - policyVariables := &networkfirewall.PolicyVariables{} + apiObject := &awstypes.PolicyVariables{} - if rvMap, ok := tfMap["rule_variables"].(*schema.Set); ok && rvMap.Len() > 0 { - policyVariables.RuleVariables = expandIPSets(rvMap.List()) + if v, ok := tfMap["rule_variables"].(*schema.Set); ok && v.Len() > 0 { + apiObject.RuleVariables = expandIPSets(v.List()) } - return policyVariables + return apiObject } -func expandStatefulEngineOptions(l []interface{}) *networkfirewall.StatefulEngineOptions { - if len(l) == 0 || l[0] == nil { +func expandStatefulEngineOptions(tfList []interface{}) *awstypes.StatefulEngineOptions { + if len(tfList) == 0 || tfList[0] == nil { return nil } - options := &networkfirewall.StatefulEngineOptions{} + apiObject := &awstypes.StatefulEngineOptions{} - m := l[0].(map[string]interface{}) - if v, ok := m["rule_order"].(string); ok && v != "" { - options.RuleOrder = aws.String(v) + tfMap := tfList[0].(map[string]interface{}) + + if v, ok := tfMap["rule_order"].(string); ok && v != "" { + apiObject.RuleOrder = awstypes.RuleOrder(v) } - if v, ok := m["stream_exception_policy"].(string); ok && v != "" { - options.StreamExceptionPolicy = aws.String(v) + if v, ok := tfMap["stream_exception_policy"].(string); ok && v != "" { + apiObject.StreamExceptionPolicy = awstypes.StreamExceptionPolicy(v) } - return options + return apiObject } -func expandStatefulRuleGroupOverride(l []interface{}) *networkfirewall.StatefulRuleGroupOverride { - if len(l) == 0 || l[0] == nil { +func expandStatefulRuleGroupOverride(tfList []interface{}) *awstypes.StatefulRuleGroupOverride { + if len(tfList) == 0 || tfList[0] == nil { return nil } - lRaw := l[0].(map[string]interface{}) - override := &networkfirewall.StatefulRuleGroupOverride{} + tfMap := tfList[0].(map[string]interface{}) + apiObject := &awstypes.StatefulRuleGroupOverride{} - if v, ok := lRaw[names.AttrAction].(string); ok && v != "" { - override.SetAction(v) + if v, ok := tfMap[names.AttrAction].(string); ok && v != "" { + apiObject.Action = awstypes.OverrideAction(v) } - return override + return apiObject } -func expandStatefulRuleGroupReferences(l []interface{}) []*networkfirewall.StatefulRuleGroupReference { - if len(l) == 0 || l[0] == nil { +func expandStatefulRuleGroupReferences(tfList []interface{}) []awstypes.StatefulRuleGroupReference { + if len(tfList) == 0 || tfList[0] == nil { return nil } - references := make([]*networkfirewall.StatefulRuleGroupReference, 0, len(l)) - for _, tfMapRaw := range l { + + apiObjects := make([]awstypes.StatefulRuleGroupReference, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - reference := &networkfirewall.StatefulRuleGroupReference{} + apiObject := awstypes.StatefulRuleGroupReference{} + + if v, ok := tfMap["override"].([]interface{}); ok && len(v) > 0 { + apiObject.Override = expandStatefulRuleGroupOverride(v) + } if v, ok := tfMap[names.AttrPriority].(int); ok && v > 0 { - reference.Priority = aws.Int64(int64(v)) + apiObject.Priority = aws.Int32(int32(v)) } if v, ok := tfMap[names.AttrResourceARN].(string); ok && v != "" { - reference.ResourceArn = aws.String(v) - } - - if v, ok := tfMap["override"].([]interface{}); ok && len(v) > 0 { - reference.Override = expandStatefulRuleGroupOverride(v) + apiObject.ResourceArn = aws.String(v) } - references = append(references, reference) + apiObjects = append(apiObjects, apiObject) } - return references + return apiObjects } -func expandStatelessRuleGroupReferences(l []interface{}) []*networkfirewall.StatelessRuleGroupReference { - if len(l) == 0 || l[0] == nil { +func expandStatelessRuleGroupReferences(tfList []interface{}) []awstypes.StatelessRuleGroupReference { + if len(tfList) == 0 || tfList[0] == nil { return nil } - references := make([]*networkfirewall.StatelessRuleGroupReference, 0, len(l)) - for _, tfMapRaw := range l { + + apiObjects := make([]awstypes.StatelessRuleGroupReference, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - reference := &networkfirewall.StatelessRuleGroupReference{} + + apiObject := awstypes.StatelessRuleGroupReference{} + if v, ok := tfMap[names.AttrPriority].(int); ok && v > 0 { - reference.Priority = aws.Int64(int64(v)) + apiObject.Priority = aws.Int32(int32(v)) } if v, ok := tfMap[names.AttrResourceARN].(string); ok && v != "" { - reference.ResourceArn = aws.String(v) + apiObject.ResourceArn = aws.String(v) } - references = append(references, reference) + + apiObjects = append(apiObjects, apiObject) } - return references + + return apiObjects } -func expandFirewallPolicy(l []interface{}) *networkfirewall.FirewallPolicy { - if len(l) == 0 || l[0] == nil { +func expandFirewallPolicy(tfList []interface{}) *awstypes.FirewallPolicy { + if len(tfList) == 0 || tfList[0] == nil { return nil } - lRaw := l[0].(map[string]interface{}) - policy := &networkfirewall.FirewallPolicy{ - StatelessDefaultActions: flex.ExpandStringSet(lRaw["stateless_default_actions"].(*schema.Set)), - StatelessFragmentDefaultActions: flex.ExpandStringSet(lRaw["stateless_fragment_default_actions"].(*schema.Set)), + + tfMap := tfList[0].(map[string]interface{}) + apiObject := &awstypes.FirewallPolicy{ + StatelessDefaultActions: flex.ExpandStringValueSet(tfMap["stateless_default_actions"].(*schema.Set)), + StatelessFragmentDefaultActions: flex.ExpandStringValueSet(tfMap["stateless_fragment_default_actions"].(*schema.Set)), } - if v, ok := lRaw["policy_variables"]; ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { - policy.PolicyVariables = expandPolicyVariables(v.([]interface{})[0].(map[string]interface{})) + if v, ok := tfMap["policy_variables"]; ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + apiObject.PolicyVariables = expandPolicyVariables(v.([]interface{})[0].(map[string]interface{})) } - if v, ok := lRaw["stateful_default_actions"].(*schema.Set); ok && v.Len() > 0 { - policy.StatefulDefaultActions = flex.ExpandStringSet(v) + if v, ok := tfMap["stateful_default_actions"].(*schema.Set); ok && v.Len() > 0 { + apiObject.StatefulDefaultActions = flex.ExpandStringValueSet(v) } - if v, ok := lRaw["stateful_engine_options"].([]interface{}); ok && len(v) > 0 { - policy.StatefulEngineOptions = expandStatefulEngineOptions(v) + if v, ok := tfMap["stateful_engine_options"].([]interface{}); ok && len(v) > 0 { + apiObject.StatefulEngineOptions = expandStatefulEngineOptions(v) } - if v, ok := lRaw["stateful_rule_group_reference"].(*schema.Set); ok && v.Len() > 0 { - policy.StatefulRuleGroupReferences = expandStatefulRuleGroupReferences(v.List()) + if v, ok := tfMap["stateful_rule_group_reference"].(*schema.Set); ok && v.Len() > 0 { + apiObject.StatefulRuleGroupReferences = expandStatefulRuleGroupReferences(v.List()) } - if v, ok := lRaw["stateless_custom_action"].(*schema.Set); ok && v.Len() > 0 { - policy.StatelessCustomActions = expandCustomActions(v.List()) + if v, ok := tfMap["stateless_custom_action"].(*schema.Set); ok && v.Len() > 0 { + apiObject.StatelessCustomActions = expandCustomActions(v.List()) } - if v, ok := lRaw["stateless_rule_group_reference"].(*schema.Set); ok && v.Len() > 0 { - policy.StatelessRuleGroupReferences = expandStatelessRuleGroupReferences(v.List()) + if v, ok := tfMap["stateless_rule_group_reference"].(*schema.Set); ok && v.Len() > 0 { + apiObject.StatelessRuleGroupReferences = expandStatelessRuleGroupReferences(v.List()) } - if v, ok := lRaw["tls_inspection_configuration_arn"].(string); ok && v != "" { - policy.TLSInspectionConfigurationArn = aws.String(v) + if v, ok := tfMap["tls_inspection_configuration_arn"].(string); ok && v != "" { + apiObject.TLSInspectionConfigurationArn = aws.String(v) } - return policy + return apiObject } -func flattenFirewallPolicy(policy *networkfirewall.FirewallPolicy) []interface{} { - if policy == nil { +func flattenFirewallPolicy(apiObject *awstypes.FirewallPolicy) []interface{} { + if apiObject == nil { return []interface{}{} } - p := map[string]interface{}{} - if policy.PolicyVariables != nil { - p["policy_variables"] = flattenPolicyVariables(policy.PolicyVariables) + + tfMap := map[string]interface{}{} + + if apiObject.PolicyVariables != nil { + tfMap["policy_variables"] = flattenPolicyVariables(apiObject.PolicyVariables) } - if policy.StatefulDefaultActions != nil { - p["stateful_default_actions"] = flex.FlattenStringSet(policy.StatefulDefaultActions) + if apiObject.StatefulDefaultActions != nil { + tfMap["stateful_default_actions"] = apiObject.StatefulDefaultActions } - if policy.StatefulEngineOptions != nil { - p["stateful_engine_options"] = flattenStatefulEngineOptions(policy.StatefulEngineOptions) + if apiObject.StatefulEngineOptions != nil { + tfMap["stateful_engine_options"] = flattenStatefulEngineOptions(apiObject.StatefulEngineOptions) } - if policy.StatefulRuleGroupReferences != nil { - p["stateful_rule_group_reference"] = flattenPolicyStatefulRuleGroupReference(policy.StatefulRuleGroupReferences) + if apiObject.StatefulRuleGroupReferences != nil { + tfMap["stateful_rule_group_reference"] = flattenPolicyStatefulRuleGroupReferences(apiObject.StatefulRuleGroupReferences) } - if policy.StatelessCustomActions != nil { - p["stateless_custom_action"] = flattenCustomActions(policy.StatelessCustomActions) + if apiObject.StatelessCustomActions != nil { + tfMap["stateless_custom_action"] = flattenCustomActions(apiObject.StatelessCustomActions) } - if policy.StatelessDefaultActions != nil { - p["stateless_default_actions"] = flex.FlattenStringSet(policy.StatelessDefaultActions) + if apiObject.StatelessDefaultActions != nil { + tfMap["stateless_default_actions"] = apiObject.StatelessDefaultActions } - if policy.StatelessFragmentDefaultActions != nil { - p["stateless_fragment_default_actions"] = flex.FlattenStringSet(policy.StatelessFragmentDefaultActions) + if apiObject.StatelessFragmentDefaultActions != nil { + tfMap["stateless_fragment_default_actions"] = apiObject.StatelessFragmentDefaultActions } - if policy.StatelessRuleGroupReferences != nil { - p["stateless_rule_group_reference"] = flattenPolicyStatelessRuleGroupReference(policy.StatelessRuleGroupReferences) + if apiObject.StatelessRuleGroupReferences != nil { + tfMap["stateless_rule_group_reference"] = flattenPolicyStatelessRuleGroupReferences(apiObject.StatelessRuleGroupReferences) } - if policy.TLSInspectionConfigurationArn != nil { - p["tls_inspection_configuration_arn"] = aws.StringValue(policy.TLSInspectionConfigurationArn) + if apiObject.TLSInspectionConfigurationArn != nil { + tfMap["tls_inspection_configuration_arn"] = aws.ToString(apiObject.TLSInspectionConfigurationArn) } - return []interface{}{p} + return []interface{}{tfMap} } -func flattenPolicyVariables(variables *networkfirewall.PolicyVariables) []interface{} { - if variables == nil { +func flattenPolicyVariables(apiObject *awstypes.PolicyVariables) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "rule_variables": flattenIPSets(variables.RuleVariables), + tfMap := map[string]interface{}{ + "rule_variables": flattenIPSets(apiObject.RuleVariables), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenStatefulEngineOptions(options *networkfirewall.StatefulEngineOptions) []interface{} { - if options == nil { +func flattenStatefulEngineOptions(apiObject *awstypes.StatefulEngineOptions) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{} - if options.RuleOrder != nil { - m["rule_order"] = aws.StringValue(options.RuleOrder) - } - if options.StreamExceptionPolicy != nil { - m["stream_exception_policy"] = aws.StringValue(options.StreamExceptionPolicy) + tfMap := map[string]interface{}{ + "rule_order": apiObject.RuleOrder, + "stream_exception_policy": apiObject.StreamExceptionPolicy, } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenStatefulRuleGroupOverride(override *networkfirewall.StatefulRuleGroupOverride) []interface{} { - if override == nil { +func flattenStatefulRuleGroupOverride(apiObject *awstypes.StatefulRuleGroupOverride) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - names.AttrAction: aws.StringValue(override.Action), + tfMap := map[string]interface{}{ + names.AttrAction: apiObject.Action, } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenPolicyStatefulRuleGroupReference(l []*networkfirewall.StatefulRuleGroupReference) []interface{} { - references := make([]interface{}, 0, len(l)) - for _, ref := range l { - reference := map[string]interface{}{ - names.AttrResourceARN: aws.StringValue(ref.ResourceArn), +func flattenPolicyStatefulRuleGroupReferences(apiObjects []awstypes.StatefulRuleGroupReference) []interface{} { + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + names.AttrResourceARN: aws.ToString(apiObject.ResourceArn), } - if ref.Priority != nil { - reference[names.AttrPriority] = int(aws.Int64Value(ref.Priority)) + + if apiObject.Override != nil { + tfMap["override"] = flattenStatefulRuleGroupOverride(apiObject.Override) } - if ref.Override != nil { - reference["override"] = flattenStatefulRuleGroupOverride(ref.Override) + if apiObject.Priority != nil { + tfMap[names.AttrPriority] = aws.ToInt32(apiObject.Priority) } - references = append(references, reference) + tfList = append(tfList, tfMap) } - return references + return tfList } -func flattenPolicyStatelessRuleGroupReference(l []*networkfirewall.StatelessRuleGroupReference) []interface{} { - references := make([]interface{}, 0, len(l)) - for _, ref := range l { - reference := map[string]interface{}{ - names.AttrPriority: int(aws.Int64Value(ref.Priority)), - names.AttrResourceARN: aws.StringValue(ref.ResourceArn), +func flattenPolicyStatelessRuleGroupReferences(apiObjects []awstypes.StatelessRuleGroupReference) []interface{} { + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + names.AttrPriority: aws.ToInt32(apiObject.Priority), + names.AttrResourceARN: aws.ToString(apiObject.ResourceArn), } - references = append(references, reference) + + tfList = append(tfList, tfMap) } - return references + + return tfList } diff --git a/internal/service/networkfirewall/firewall_policy_test.go b/internal/service/networkfirewall/firewall_policy_test.go index 625e151adbf..21e4ff97e67 100644 --- a/internal/service/networkfirewall/firewall_policy_test.go +++ b/internal/service/networkfirewall/firewall_policy_test.go @@ -8,8 +8,9 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -225,8 +226,8 @@ func TestAccNetworkFirewallFirewallPolicy_statefulEngineOption(t *testing.T) { testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy), resource.TestCheckResourceAttr(resourceName, "firewall_policy.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", networkfirewall.RuleOrderStrictOrder), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", networkfirewall.StreamExceptionPolicyDrop), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", string(awstypes.RuleOrderStrictOrder)), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", string(awstypes.StreamExceptionPolicyDrop)), ), }, { @@ -256,8 +257,8 @@ func TestAccNetworkFirewallFirewallPolicy_updateStatefulEngineOption(t *testing. testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy1), resource.TestCheckResourceAttr(resourceName, "firewall_policy.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", networkfirewall.RuleOrderDefaultActionOrder), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", networkfirewall.StreamExceptionPolicyContinue), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", string(awstypes.RuleOrderDefaultActionOrder)), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", string(awstypes.StreamExceptionPolicyContinue)), ), }, { @@ -275,8 +276,8 @@ func TestAccNetworkFirewallFirewallPolicy_updateStatefulEngineOption(t *testing. testAccCheckFirewallPolicyRecreated(&firewallPolicy2, &firewallPolicy3), resource.TestCheckResourceAttr(resourceName, "firewall_policy.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", networkfirewall.RuleOrderStrictOrder), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", networkfirewall.StreamExceptionPolicyReject), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", string(awstypes.RuleOrderStrictOrder)), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", string(awstypes.StreamExceptionPolicyReject)), ), }, { @@ -306,7 +307,7 @@ func TestAccNetworkFirewallFirewallPolicy_statefulEngineOptionsSingle(t *testing testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy), resource.TestCheckResourceAttr(resourceName, "firewall_policy.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", networkfirewall.RuleOrderDefaultActionOrder), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", string(awstypes.RuleOrderDefaultActionOrder)), resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", ""), ), }, @@ -317,7 +318,7 @@ func TestAccNetworkFirewallFirewallPolicy_statefulEngineOptionsSingle(t *testing resource.TestCheckResourceAttr(resourceName, "firewall_policy.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.rule_order", ""), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", networkfirewall.StreamExceptionPolicyReject), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_engine_options.0.stream_exception_policy", string(awstypes.StreamExceptionPolicyReject)), ), }, { @@ -511,7 +512,7 @@ func TestAccNetworkFirewallFirewallPolicy_statefulRuleGroupOverrideActionReferen var firewallPolicy networkfirewall.DescribeFirewallPolicyOutput rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_networkfirewall_firewall_policy.test" - override_action := networkfirewall.OverrideActionDropToAlert + overrideAction := string(awstypes.OverrideActionDropToAlert) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, @@ -520,10 +521,10 @@ func TestAccNetworkFirewallFirewallPolicy_statefulRuleGroupOverrideActionReferen CheckDestroy: testAccCheckFirewallPolicyDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccFirewallPolicyConfig_statefulRuleGroupReferenceManagedOverrideAction(rName, override_action), + Config: testAccFirewallPolicyConfig_statefulRuleGroupReferenceManagedOverrideAction(rName, overrideAction), Check: resource.ComposeTestCheckFunc( testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy), - resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_rule_group_reference.0.override.0.action", override_action), + resource.TestCheckResourceAttr(resourceName, "firewall_policy.0.stateful_rule_group_reference.0.override.0.action", overrideAction), ), }, { @@ -1039,7 +1040,7 @@ func testAccCheckFirewallPolicyDestroy(ctx context.Context) resource.TestCheckFu continue } - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) _, err := tfnetworkfirewall.FindFirewallPolicyByARN(ctx, conn, rs.Primary.ID) @@ -1065,11 +1066,7 @@ func testAccCheckFirewallPolicyExists(ctx context.Context, n string, v *networkf return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No NetworkFirewall Firewall Policy ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) output, err := tfnetworkfirewall.FindFirewallPolicyByARN(ctx, conn, rs.Primary.ID) @@ -1085,7 +1082,7 @@ func testAccCheckFirewallPolicyExists(ctx context.Context, n string, v *networkf func testAccCheckFirewallPolicyNotRecreated(i, j *networkfirewall.DescribeFirewallPolicyOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - if before, after := aws.StringValue(i.FirewallPolicyResponse.FirewallPolicyId), aws.StringValue(j.FirewallPolicyResponse.FirewallPolicyId); before != after { + if before, after := aws.ToString(i.FirewallPolicyResponse.FirewallPolicyId), aws.ToString(j.FirewallPolicyResponse.FirewallPolicyId); before != after { return fmt.Errorf("NetworkFirewall Firewall Policy was recreated. got: %s, expected: %s", after, before) } return nil @@ -1094,7 +1091,7 @@ func testAccCheckFirewallPolicyNotRecreated(i, j *networkfirewall.DescribeFirewa func testAccCheckFirewallPolicyRecreated(i, j *networkfirewall.DescribeFirewallPolicyOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - if before, after := aws.StringValue(i.FirewallPolicyResponse.FirewallPolicyId), aws.StringValue(j.FirewallPolicyResponse.FirewallPolicyId); before == after { + if before, after := aws.ToString(i.FirewallPolicyResponse.FirewallPolicyId), aws.ToString(j.FirewallPolicyResponse.FirewallPolicyId); before == after { return fmt.Errorf("NetworkFirewall Firewall Policy (%s) was not recreated", before) } return nil diff --git a/internal/service/networkfirewall/helpers.go b/internal/service/networkfirewall/helpers.go index 9d0d4ab8242..cd3b4f11752 100644 --- a/internal/service/networkfirewall/helpers.go +++ b/internal/service/networkfirewall/helpers.go @@ -5,10 +5,12 @@ package networkfirewall import ( "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/aws" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "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/enum" + "github.com/hashicorp/terraform-provider-aws/internal/flex" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -24,44 +26,49 @@ func encryptionConfigurationSchema() *schema.Schema { Optional: true, }, names.AttrType: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.EncryptionType_Values(), false), + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.EncryptionType](), }, }, }, } } -func expandEncryptionConfiguration(tfList []interface{}) *networkfirewall.EncryptionConfiguration { - ec := &networkfirewall.EncryptionConfiguration{Type: aws.String(networkfirewall.EncryptionTypeAwsOwnedKmsKey)} +func expandEncryptionConfiguration(tfList []interface{}) *awstypes.EncryptionConfiguration { + apiObject := &awstypes.EncryptionConfiguration{ + Type: awstypes.EncryptionTypeAwsOwnedKmsKey, + } + if len(tfList) == 1 && tfList[0] != nil { tfMap := tfList[0].(map[string]interface{}) + if v, ok := tfMap[names.AttrKeyID].(string); ok { - ec.KeyId = aws.String(v) + apiObject.KeyId = aws.String(v) } if v, ok := tfMap[names.AttrType].(string); ok { - ec.Type = aws.String(v) + apiObject.Type = awstypes.EncryptionType(v) } } - return ec + return apiObject } -func flattenEncryptionConfiguration(apiObject *networkfirewall.EncryptionConfiguration) []interface{} { - if apiObject == nil || apiObject.Type == nil { +func flattenEncryptionConfiguration(apiObject *awstypes.EncryptionConfiguration) []interface{} { + if apiObject == nil || apiObject.Type == "" { return nil } - if aws.StringValue(apiObject.Type) == networkfirewall.EncryptionTypeAwsOwnedKmsKey { + + if apiObject.Type == awstypes.EncryptionTypeAwsOwnedKmsKey { return nil } - m := map[string]interface{}{ - names.AttrKeyID: aws.StringValue(apiObject.KeyId), - names.AttrType: aws.StringValue(apiObject.Type), + tfMap := map[string]interface{}{ + names.AttrKeyID: aws.ToString(apiObject.KeyId), + names.AttrType: apiObject.Type, } - return []interface{}{m} + return []interface{}{tfMap} } func customActionSchema() *schema.Schema { @@ -111,178 +118,212 @@ func customActionSchema() *schema.Schema { } } -func expandCustomActions(l []interface{}) []*networkfirewall.CustomAction { - if len(l) == 0 || l[0] == nil { +func expandCustomActions(tfList []interface{}) []awstypes.CustomAction { + if len(tfList) == 0 || tfList[0] == nil { return nil } - customActions := make([]*networkfirewall.CustomAction, 0, len(l)) - for _, tfMapRaw := range l { - customAction := &networkfirewall.CustomAction{} + apiObjects := make([]awstypes.CustomAction, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } + + apiObject := awstypes.CustomAction{} + if v, ok := tfMap["action_definition"].([]interface{}); ok && len(v) > 0 && v[0] != nil { - customAction.ActionDefinition = expandActionDefinition(v) + apiObject.ActionDefinition = expandActionDefinition(v) } if v, ok := tfMap["action_name"].(string); ok && v != "" { - customAction.ActionName = aws.String(v) + apiObject.ActionName = aws.String(v) } - customActions = append(customActions, customAction) + + apiObjects = append(apiObjects, apiObject) } - return customActions + return apiObjects } -func expandActionDefinition(l []interface{}) *networkfirewall.ActionDefinition { - if l == nil || l[0] == nil { +func expandActionDefinition(tfList []interface{}) *awstypes.ActionDefinition { + if tfList == nil || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - customAction := &networkfirewall.ActionDefinition{} + + apiObject := &awstypes.ActionDefinition{} if v, ok := tfMap["publish_metric_action"].([]interface{}); ok && len(v) > 0 && v[0] != nil { - customAction.PublishMetricAction = expandCustomActionPublishMetricAction(v) + apiObject.PublishMetricAction = expandPublishMetricAction(v) } - return customAction + return apiObject } -func expandCustomActionPublishMetricAction(l []interface{}) *networkfirewall.PublishMetricAction { - if len(l) == 0 || l[0] == nil { +func expandPublishMetricAction(tfList []interface{}) *awstypes.PublishMetricAction { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - action := &networkfirewall.PublishMetricAction{} - if tfSet, ok := tfMap["dimension"].(*schema.Set); ok && tfSet.Len() > 0 { - tfList := tfSet.List() - dimensions := make([]*networkfirewall.Dimension, 0, len(tfList)) + + apiObject := &awstypes.PublishMetricAction{} + + if v, ok := tfMap["dimension"].(*schema.Set); ok && v.Len() > 0 { + tfList := v.List() + dimensions := make([]awstypes.Dimension, 0, len(tfList)) + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - dimension := &networkfirewall.Dimension{ + + dimensions = append(dimensions, awstypes.Dimension{ Value: aws.String(tfMap[names.AttrValue].(string)), - } - dimensions = append(dimensions, dimension) + }) } - action.Dimensions = dimensions + + apiObject.Dimensions = dimensions } - return action + + return apiObject } -func flattenCustomActions(c []*networkfirewall.CustomAction) []interface{} { - if c == nil { +func flattenCustomActions(apiObjects []awstypes.CustomAction) []interface{} { + if apiObjects == nil { return []interface{}{} } - customActions := make([]interface{}, 0, len(c)) - for _, elem := range c { - m := map[string]interface{}{ - "action_definition": flattenActionDefinition(elem.ActionDefinition), - "action_name": aws.StringValue(elem.ActionName), + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + "action_definition": flattenActionDefinition(apiObject.ActionDefinition), + "action_name": aws.ToString(apiObject.ActionName), } - customActions = append(customActions, m) + + tfList = append(tfList, tfMap) } - return customActions + return tfList } -func flattenActionDefinition(v *networkfirewall.ActionDefinition) []interface{} { - if v == nil { +func flattenActionDefinition(apiObject *awstypes.ActionDefinition) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "publish_metric_action": flattenPublishMetricAction(v.PublishMetricAction), + + tfMap := map[string]interface{}{ + "publish_metric_action": flattenPublishMetricAction(apiObject.PublishMetricAction), } - return []interface{}{m} + + return []interface{}{tfMap} } -func flattenPublishMetricAction(m *networkfirewall.PublishMetricAction) []interface{} { - if m == nil { +func flattenPublishMetricAction(apiObject *awstypes.PublishMetricAction) []interface{} { + if apiObject == nil { return []interface{}{} } - metrics := map[string]interface{}{ - "dimension": flattenDimensions(m.Dimensions), + tfMap := map[string]interface{}{ + "dimension": flattenDimensions(apiObject.Dimensions), } - return []interface{}{metrics} + return []interface{}{tfMap} } -func flattenDimensions(d []*networkfirewall.Dimension) []interface{} { - dimensions := make([]interface{}, 0, len(d)) - for _, v := range d { - dimension := map[string]interface{}{ - names.AttrValue: aws.StringValue(v.Value), - } - dimensions = append(dimensions, dimension) +func flattenDimensions(apiObjects []awstypes.Dimension) []interface{} { + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfList = append(tfList, map[string]interface{}{ + names.AttrValue: aws.ToString(apiObject.Value), + }) } - return dimensions + return tfList } func forceNewIfNotRuleOrderDefault(key string, d *schema.ResourceDiff) error { if d.Id() != "" && d.HasChange(key) { old, new := d.GetChange(key) - defaultRuleOrderOld := old == nil || old.(string) == "" || old.(string) == networkfirewall.RuleOrderDefaultActionOrder - defaultRuleOrderNew := new == nil || new.(string) == "" || new.(string) == networkfirewall.RuleOrderDefaultActionOrder + defaultRuleOrderOld := old == nil || old.(string) == "" || old.(string) == string(awstypes.RuleOrderDefaultActionOrder) + defaultRuleOrderNew := new == nil || new.(string) == "" || new.(string) == string(awstypes.RuleOrderDefaultActionOrder) if (defaultRuleOrderOld && !defaultRuleOrderNew) || (defaultRuleOrderNew && !defaultRuleOrderOld) { return d.ForceNew(key) } } + return nil } -func customActionSchemaDataSource() *schema.Schema { - return &schema.Schema{ - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_definition": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "publish_metric_action": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dimension": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrValue: { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - "action_name": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, +func expandIPSets(tfList []interface{}) map[string]awstypes.IPSet { + if len(tfList) == 0 || tfList[0] == nil { + return nil } + + apiObject := make(map[string]awstypes.IPSet) + + for _, tfMapRaw := range tfList { + tfMap, ok := tfMapRaw.(map[string]interface{}) + if !ok { + continue + } + + if k, ok := tfMap[names.AttrKey].(string); ok && k != "" { + if tfList, ok := tfMap["ip_set"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { + tfMap, ok := tfList[0].(map[string]interface{}) + if !ok { + continue + } + + if v, ok := tfMap["definition"].(*schema.Set); ok && v.Len() > 0 { + apiObject[k] = awstypes.IPSet{ + Definition: flex.ExpandStringValueSet(v), + } + } + } + } + } + + return apiObject +} + +func flattenIPSets(tfMap map[string]awstypes.IPSet) []interface{} { + if tfMap == nil { + return []interface{}{} + } + + tfList := make([]interface{}, 0, len(tfMap)) + + for k, v := range tfMap { + tfList = append(tfList, map[string]interface{}{ + names.AttrKey: k, + "ip_set": flattenIPSet(&v), + }) + } + + return tfList +} + +func flattenIPSet(apiObject *awstypes.IPSet) []interface{} { + if apiObject == nil { + return []interface{}{} + } + + tfMap := map[string]interface{}{ + "definition": apiObject.Definition, + } + + return []interface{}{tfMap} } diff --git a/internal/service/networkfirewall/rule_group.go b/internal/service/networkfirewall/rule_group.go index 133f2691717..8a8e441054e 100644 --- a/internal/service/networkfirewall/rule_group.go +++ b/internal/service/networkfirewall/rule_group.go @@ -844,35 +844,6 @@ func expandRuleGroup(tfMap map[string]interface{}) *networkfirewall.RuleGroup { return ruleGroup } -func expandIPSets(l []interface{}) map[string]*networkfirewall.IPSet { - if len(l) == 0 || l[0] == nil { - return nil - } - - m := make(map[string]*networkfirewall.IPSet) - for _, tfMapRaw := range l { - tfMap, ok := tfMapRaw.(map[string]interface{}) - if !ok { - continue - } - - if key, ok := tfMap[names.AttrKey].(string); ok && key != "" { - if tfList, ok := tfMap["ip_set"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { - tfMap, ok := tfList[0].(map[string]interface{}) - if ok { - if tfSet, ok := tfMap["definition"].(*schema.Set); ok && tfSet.Len() > 0 { - ipSet := &networkfirewall.IPSet{ - Definition: flex.ExpandStringSet(tfSet), - } - m[key] = ipSet - } - } - } - } - } - - return m -} func expandIPSetReferences(l []interface{}) map[string]*networkfirewall.IPSetReference { if len(l) == 0 || l[0] == nil { return nil @@ -1153,22 +1124,6 @@ func flattenRuleVariables(rv *networkfirewall.RuleVariables) []interface{} { return []interface{}{m} } -func flattenIPSets(m map[string]*networkfirewall.IPSet) []interface{} { - if m == nil { - return []interface{}{} - } - sets := make([]interface{}, 0, len(m)) - for k, v := range m { - tfMap := map[string]interface{}{ - names.AttrKey: k, - "ip_set": flattenIPSet(v), - } - sets = append(sets, tfMap) - } - - return sets -} - func flattenPortSets(m map[string]*networkfirewall.PortSet) []interface{} { if m == nil { return []interface{}{} @@ -1185,17 +1140,6 @@ func flattenPortSets(m map[string]*networkfirewall.PortSet) []interface{} { return sets } -func flattenIPSet(i *networkfirewall.IPSet) []interface{} { - if i == nil { - return []interface{}{} - } - m := map[string]interface{}{ - "definition": flex.FlattenStringSet(i.Definition), - } - - return []interface{}{m} -} - func flattenPortSet(p *networkfirewall.PortSet) []interface{} { if p == nil { return []interface{}{} diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index bceb430bf92..8ac42bb777b 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -60,7 +60,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka }, }, { - Factory: ResourceFirewallPolicy, + Factory: resourceFirewallPolicy, TypeName: "aws_networkfirewall_firewall_policy", Name: "Firewall Policy", Tags: &types.ServicePackageResourceTags{ From 9586f4c37f8ea2e6e9b67fa1e1e74b15d0a9017c Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 11:05:47 -0400 Subject: [PATCH 58/68] d/aws_networkfirewall_firewall_policy: Migrate to AWS SDK for Go v2. --- internal/service/networkfirewall/find.go | 29 --- .../networkfirewall/firewall_policy.go | 14 +- .../firewall_policy_data_source.go | 246 +++++++++--------- .../firewall_policy_data_source_test.go | 9 - .../networkfirewall/service_package_gen.go | 4 +- 5 files changed, 131 insertions(+), 171 deletions(-) delete mode 100644 internal/service/networkfirewall/find.go diff --git a/internal/service/networkfirewall/find.go b/internal/service/networkfirewall/find.go deleted file mode 100644 index 98154f36253..00000000000 --- a/internal/service/networkfirewall/find.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package networkfirewall - -import ( - "context" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" -) - -// FindFirewallPolicyByNameAndARN returns the FirewallPolicyOutput from a call to DescribeFirewallPolicyWithContext -// given the context and at least one of FirewallPolicyArn and FirewallPolicyName. -func FindFirewallPolicyByNameAndARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, name string) (*networkfirewall.DescribeFirewallPolicyOutput, error) { - input := &networkfirewall.DescribeFirewallPolicyInput{} - if arn != "" { - input.FirewallPolicyArn = aws.String(arn) - } - if name != "" { - input.FirewallPolicyName = aws.String(name) - } - - output, err := conn.DescribeFirewallPolicyWithContext(ctx, input) - if err != nil { - return nil, err - } - return output, nil -} diff --git a/internal/service/networkfirewall/firewall_policy.go b/internal/service/networkfirewall/firewall_policy.go index b560b4ad07a..3b05e33701a 100644 --- a/internal/service/networkfirewall/firewall_policy.go +++ b/internal/service/networkfirewall/firewall_policy.go @@ -335,11 +335,7 @@ func resourceFirewallPolicyDelete(ctx context.Context, d *schema.ResourceData, m return diags } -func findFirewallPolicyByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeFirewallPolicyOutput, error) { - input := &networkfirewall.DescribeFirewallPolicyInput{ - FirewallPolicyArn: aws.String(arn), - } - +func findFirewallPolicy(ctx context.Context, conn *networkfirewall.Client, input *networkfirewall.DescribeFirewallPolicyInput) (*networkfirewall.DescribeFirewallPolicyOutput, error) { output, err := conn.DescribeFirewallPolicy(ctx, input) if errs.IsA[*awstypes.ResourceNotFoundException](err) { @@ -360,6 +356,14 @@ func findFirewallPolicyByARN(ctx context.Context, conn *networkfirewall.Client, return output, nil } +func findFirewallPolicyByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeFirewallPolicyOutput, error) { + input := &networkfirewall.DescribeFirewallPolicyInput{ + FirewallPolicyArn: aws.String(arn), + } + + return findFirewallPolicy(ctx, conn, input) +} + func statusFirewallPolicy(ctx context.Context, conn *networkfirewall.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { output, err := findFirewallPolicyByARN(ctx, conn, arn) diff --git a/internal/service/networkfirewall/firewall_policy_data_source.go b/internal/service/networkfirewall/firewall_policy_data_source.go index a53040a7ca0..fcabb20d3fa 100644 --- a/internal/service/networkfirewall/firewall_policy_data_source.go +++ b/internal/service/networkfirewall/firewall_policy_data_source.go @@ -5,181 +5,173 @@ package networkfirewall import ( "context" - "log" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" "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/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/sdkv2" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) -// @SDKDataSource("aws_networkfirewall_firewall_policy") -func DataSourceFirewallPolicy() *schema.Resource { +// @SDKDataSource("aws_networkfirewall_firewall_policy", name="Firewall Policy") +// @Tags +func dataSourceFirewallPolicy() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceFirewallPolicyRead, - Schema: map[string]*schema.Schema{ - names.AttrARN: { - Type: schema.TypeString, - AtLeastOneOf: []string{names.AttrARN, names.AttrName}, - Optional: true, - ValidateFunc: verify.ValidARN, - }, - names.AttrDescription: { - Type: schema.TypeString, - Computed: true, - }, - "firewall_policy": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "stateful_default_actions": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "stateful_engine_options": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "rule_order": { - Type: schema.TypeString, - Computed: true, - }, - "stream_exception_policy": { - Type: schema.TypeString, - Computed: true, + + SchemaFunc: func() map[string]*schema.Schema { + return map[string]*schema.Schema{ + names.AttrARN: { + Type: schema.TypeString, + AtLeastOneOf: []string{names.AttrARN, names.AttrName}, + Optional: true, + ValidateFunc: verify.ValidARN, + }, + names.AttrDescription: { + Type: schema.TypeString, + Computed: true, + }, + "firewall_policy": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "stateful_default_actions": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "stateful_engine_options": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rule_order": { + Type: schema.TypeString, + Computed: true, + }, + "stream_exception_policy": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, - }, - "stateful_rule_group_reference": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "override": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrAction: { - Type: schema.TypeString, - Optional: true, + "stateful_rule_group_reference": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "override": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrAction: { + Type: schema.TypeString, + Optional: true, + }, }, }, }, - }, - names.AttrPriority: { - Type: schema.TypeInt, - Computed: true, - }, - names.AttrResourceARN: { - Type: schema.TypeString, - Computed: true, + names.AttrPriority: { + Type: schema.TypeInt, + Computed: true, + }, + names.AttrResourceARN: { + Type: schema.TypeString, + Computed: true, + }, }, }, }, - }, - "stateless_custom_action": customActionSchemaDataSource(), - "stateless_default_actions": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "stateless_fragment_default_actions": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "stateless_rule_group_reference": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrPriority: { - Type: schema.TypeInt, - Computed: true, - }, - names.AttrResourceARN: { - Type: schema.TypeString, - Computed: true, + "stateless_custom_action": sdkv2.DataSourcePropertyFromResourceProperty(customActionSchema()), + "stateless_default_actions": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "stateless_fragment_default_actions": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "stateless_rule_group_reference": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrPriority: { + Type: schema.TypeInt, + Computed: true, + }, + names.AttrResourceARN: { + Type: schema.TypeString, + Computed: true, + }, }, }, }, - }, - "tls_inspection_configuration_arn": { - Type: schema.TypeString, - Computed: true, + "tls_inspection_configuration_arn": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, - }, - names.AttrName: { - Type: schema.TypeString, - Optional: true, - AtLeastOneOf: []string{names.AttrARN, names.AttrName}, - ValidateFunc: validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z-]{1,128}$`), "Must have 1-128 valid characters: a-z, A-Z, 0-9 and -(hyphen)"), - }, - names.AttrTags: tftags.TagsSchemaComputed(), - "update_token": { - Type: schema.TypeString, - Computed: true, - }, + names.AttrName: { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: []string{names.AttrARN, names.AttrName}, + ValidateFunc: validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z-]{1,128}$`), "Must have 1-128 valid characters: a-z, A-Z, 0-9 and -(hyphen)"), + }, + names.AttrTags: tftags.TagsSchemaComputed(), + "update_token": { + Type: schema.TypeString, + Computed: true, + }, + } }, } } func dataSourceFirewallPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig - - arn := d.Get(names.AttrARN).(string) - name := d.Get(names.AttrName).(string) - - log.Printf("[DEBUG] Reading NetworkFirewall Firewall Policy %s %s", arn, name) + input := &networkfirewall.DescribeFirewallPolicyInput{} + if v := d.Get(names.AttrARN).(string); v != "" { + input.FirewallPolicyArn = aws.String(v) + } + if v := d.Get(names.AttrName).(string); v != "" { + input.FirewallPolicyName = aws.String(v) + } - output, err := FindFirewallPolicyByNameAndARN(ctx, conn, arn, name) + output, err := findFirewallPolicy(ctx, conn, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Firewall Policy (%s, %s): %s", arn, name, err) - } - - if output == nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Firewall Policy (%s, %s): empty output", arn, name) - } - if output.FirewallPolicyResponse == nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Firewall Policy (%s, %s): empty output.FirewallPolicyResponse", arn, name) + return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Firewall Policy: %s", err) } resp := output.FirewallPolicyResponse - policy := output.FirewallPolicy - - d.SetId(aws.StringValue(resp.FirewallPolicyArn)) + d.SetId(aws.ToString(resp.FirewallPolicyArn)) d.Set(names.AttrARN, resp.FirewallPolicyArn) d.Set(names.AttrDescription, resp.Description) - d.Set(names.AttrName, resp.FirewallPolicyName) - d.Set("update_token", output.UpdateToken) - - if err := d.Set("firewall_policy", flattenFirewallPolicy(policy)); err != nil { + if err := d.Set("firewall_policy", flattenFirewallPolicy(output.FirewallPolicy)); err != nil { return sdkdiag.AppendErrorf(diags, "setting firewall_policy: %s", err) } + d.Set(names.AttrName, resp.FirewallPolicyName) + d.Set("update_token", output.UpdateToken) - tags := KeyValueTags(ctx, resp.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig) - - if err := d.Set(names.AttrTags, tags.Map()); err != nil { - return sdkdiag.AppendErrorf(diags, "setting tags: %s", err) - } + setTagsOut(ctx, resp.Tags) return diags } diff --git a/internal/service/networkfirewall/firewall_policy_data_source_test.go b/internal/service/networkfirewall/firewall_policy_data_source_test.go index 72d06b0e6e5..cb0f80fb7bc 100644 --- a/internal/service/networkfirewall/firewall_policy_data_source_test.go +++ b/internal/service/networkfirewall/firewall_policy_data_source_test.go @@ -7,7 +7,6 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/service/networkfirewall" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/acctest" @@ -16,7 +15,6 @@ import ( func TestAccNetworkFirewallFirewallPolicyDataSource_arn(t *testing.T) { ctx := acctest.Context(t) - var firewallPolicy networkfirewall.DescribeFirewallPolicyOutput rName := sdkacctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_networkfirewall_firewall_policy.test" datasourceName := "data.aws_networkfirewall_firewall_policy.test" @@ -29,7 +27,6 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_arn(t *testing.T) { { Config: testAccFirewallPolicyDataSourceConfig_arn(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy), resource.TestCheckResourceAttrPair(datasourceName, names.AttrARN, resourceName, names.AttrARN), resource.TestCheckResourceAttrPair(datasourceName, names.AttrDescription, resourceName, names.AttrDescription), resource.TestCheckResourceAttrPair(datasourceName, "firewall_policy.#", resourceName, "firewall_policy.#"), @@ -48,7 +45,6 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_arn(t *testing.T) { func TestAccNetworkFirewallFirewallPolicyDataSource_name(t *testing.T) { ctx := acctest.Context(t) - var firewallPolicy networkfirewall.DescribeFirewallPolicyOutput rName := sdkacctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_networkfirewall_firewall_policy.test" datasourceName := "data.aws_networkfirewall_firewall_policy.test" @@ -61,7 +57,6 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_name(t *testing.T) { { Config: testAccFirewallPolicyDataSourceConfig_name(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy), resource.TestCheckResourceAttrPair(datasourceName, names.AttrARN, resourceName, names.AttrARN), resource.TestCheckResourceAttrPair(datasourceName, names.AttrDescription, resourceName, names.AttrDescription), resource.TestCheckResourceAttrPair(datasourceName, "firewall_policy.#", resourceName, "firewall_policy.#"), @@ -80,7 +75,6 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_name(t *testing.T) { func TestAccNetworkFirewallFirewallPolicyDataSource_nameAndARN(t *testing.T) { ctx := acctest.Context(t) - var firewallPolicy networkfirewall.DescribeFirewallPolicyOutput rName := sdkacctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_networkfirewall_firewall_policy.test" datasourceName := "data.aws_networkfirewall_firewall_policy.test" @@ -93,7 +87,6 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_nameAndARN(t *testing.T) { { Config: testAccFirewallPolicyDataSourceConfig_nameAndARN(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy), resource.TestCheckResourceAttrPair(datasourceName, names.AttrARN, resourceName, names.AttrARN), resource.TestCheckResourceAttrPair(datasourceName, names.AttrDescription, resourceName, names.AttrDescription), resource.TestCheckResourceAttrPair(datasourceName, "firewall_policy.#", resourceName, "firewall_policy.#"), @@ -112,7 +105,6 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_nameAndARN(t *testing.T) { func TestAccNetworkFirewallFirewallPolicyDataSource_withOverriddenManagedRuleGroup(t *testing.T) { ctx := acctest.Context(t) - var firewallPolicy networkfirewall.DescribeFirewallPolicyOutput rName := sdkacctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_networkfirewall_firewall_policy.test" datasourceName := "data.aws_networkfirewall_firewall_policy.test" @@ -125,7 +117,6 @@ func TestAccNetworkFirewallFirewallPolicyDataSource_withOverriddenManagedRuleGro { Config: testAccFirewallPolicyDataSourceConfig_withOverriddenManagedRuleGroup(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckFirewallPolicyExists(ctx, resourceName, &firewallPolicy), resource.TestCheckResourceAttrPair(datasourceName, names.AttrARN, resourceName, names.AttrARN), resource.TestCheckResourceAttrPair(datasourceName, names.AttrDescription, resourceName, names.AttrDescription), resource.TestCheckResourceAttrPair(datasourceName, "firewall_policy.#", resourceName, "firewall_policy.#"), resource.TestCheckResourceAttrPair(datasourceName, "firewall_policy.0.stateless_fragment_default_actions.#", resourceName, "firewall_policy.0.stateless_fragment_default_actions.#"), diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 8ac42bb777b..4ce6af9c080 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -38,8 +38,10 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac TypeName: "aws_networkfirewall_firewall", }, { - Factory: DataSourceFirewallPolicy, + Factory: dataSourceFirewallPolicy, TypeName: "aws_networkfirewall_firewall_policy", + Name: "Firewall Policy", + Tags: &types.ServicePackageResourceTags{}, }, { Factory: dataSourceResourcePolicy, From 52fca18c2093a913330042ca8853b1b208185c02 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 11:35:04 -0400 Subject: [PATCH 59/68] r/aws_networkfirewall_firewall: Migrate to AWS SDK for Go v2. --- .../service/networkfirewall/exports_test.go | 2 + internal/service/networkfirewall/firewall.go | 402 +++++++++--------- .../service/networkfirewall/firewall_test.go | 19 +- .../networkfirewall/service_package_gen.go | 2 +- 4 files changed, 210 insertions(+), 215 deletions(-) diff --git a/internal/service/networkfirewall/exports_test.go b/internal/service/networkfirewall/exports_test.go index 16b39e3785c..4711dcfac7c 100644 --- a/internal/service/networkfirewall/exports_test.go +++ b/internal/service/networkfirewall/exports_test.go @@ -5,11 +5,13 @@ package networkfirewall // Exports for use in tests only. var ( + ResourceFirewall = resourceFirewall ResourceFirewallPolicy = resourceFirewallPolicy ResourceLoggingConfiguration = resourceLoggingConfiguration ResourceResourcePolicy = resourceResourcePolicy ResourceTLSInspectionConfiguration = newTLSInspectionConfigurationResource + FindFirewallByARN = findFirewallByARN FindFirewallPolicyByARN = findFirewallPolicyByARN FindLoggingConfigurationByARN = findLoggingConfigurationByARN FindResourcePolicyByARN = findResourcePolicyByARN diff --git a/internal/service/networkfirewall/firewall.go b/internal/service/networkfirewall/firewall.go index 95dceedc33e..51ba55fff55 100644 --- a/internal/service/networkfirewall/firewall.go +++ b/internal/service/networkfirewall/firewall.go @@ -4,23 +4,22 @@ package networkfirewall import ( - "bytes" "context" - "fmt" "log" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "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/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/sdkv2" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" @@ -29,7 +28,7 @@ import ( // @SDKResource("aws_networkfirewall_firewall", name="Firewall") // @Tags(identifierAttribute="id") -func ResourceFirewall() *schema.Resource { +func resourceFirewall() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceFirewallCreate, ReadWithoutTimeout: resourceFirewallRead, @@ -53,56 +52,58 @@ func ResourceFirewall() *schema.Resource { verify.SetTagsDiff, ), - Schema: map[string]*schema.Schema{ - names.AttrARN: { - Type: schema.TypeString, - Computed: true, - }, - "delete_protection": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - names.AttrDescription: { - Type: schema.TypeString, - Optional: true, - }, - names.AttrEncryptionConfiguration: encryptionConfigurationSchema(), - "firewall_policy_arn": { - Type: schema.TypeString, - Required: true, - ValidateFunc: verify.ValidARN, - }, - "firewall_policy_change_protection": { - Type: schema.TypeBool, - Optional: true, - }, - "firewall_status": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "sync_states": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrAvailabilityZone: { - Type: schema.TypeString, - Computed: true, - }, - "attachment": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "endpoint_id": { - Type: schema.TypeString, - Computed: true, - }, - names.AttrSubnetID: { - Type: schema.TypeString, - Computed: true, + SchemaFunc: func() map[string]*schema.Schema { + return map[string]*schema.Schema{ + names.AttrARN: { + Type: schema.TypeString, + Computed: true, + }, + "delete_protection": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + names.AttrDescription: { + Type: schema.TypeString, + Optional: true, + }, + names.AttrEncryptionConfiguration: encryptionConfigurationSchema(), + "firewall_policy_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, + "firewall_policy_change_protection": { + Type: schema.TypeBool, + Optional: true, + }, + "firewall_status": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "sync_states": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrAvailabilityZone: { + Type: schema.TypeString, + Computed: true, + }, + "attachment": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "endpoint_id": { + Type: schema.TypeString, + Computed: true, + }, + names.AttrSubnetID: { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -112,53 +113,52 @@ func ResourceFirewall() *schema.Resource { }, }, }, - }, - names.AttrName: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "subnet_change_protection": { - Type: schema.TypeBool, - Optional: true, - }, - "subnet_mapping": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrIPAddressType: { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validation.StringInSlice(networkfirewall.IPAddressType_Values(), false), - }, - names.AttrSubnetID: { - Type: schema.TypeString, - Required: true, + names.AttrName: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "subnet_change_protection": { + Type: schema.TypeBool, + Optional: true, + }, + "subnet_mapping": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrIPAddressType: { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateDiagFunc: enum.Validate[awstypes.IPAddressType](), + }, + names.AttrSubnetID: { + Type: schema.TypeString, + Required: true, + }, }, }, }, - }, - names.AttrTags: tftags.TagsSchema(), - names.AttrTagsAll: tftags.TagsSchemaComputed(), - "update_token": { - Type: schema.TypeString, - Computed: true, - }, - names.AttrVPCID: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), + "update_token": { + Type: schema.TypeString, + Computed: true, + }, + names.AttrVPCID: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + } }, } } func resourceFirewallCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) name := d.Get(names.AttrName).(string) input := &networkfirewall.CreateFirewallInput{ @@ -170,7 +170,7 @@ func resourceFirewallCreate(ctx context.Context, d *schema.ResourceData, meta in } if v, ok := d.GetOk("delete_protection"); ok { - input.DeleteProtection = aws.Bool(v.(bool)) + input.DeleteProtection = v.(bool) } if v, ok := d.GetOk(names.AttrDescription); ok { @@ -182,20 +182,20 @@ func resourceFirewallCreate(ctx context.Context, d *schema.ResourceData, meta in } if v, ok := d.GetOk("firewall_policy_change_protection"); ok { - input.FirewallPolicyChangeProtection = aws.Bool(v.(bool)) + input.FirewallPolicyChangeProtection = v.(bool) } if v, ok := d.GetOk("subnet_change_protection"); ok { - input.SubnetChangeProtection = aws.Bool(v.(bool)) + input.SubnetChangeProtection = v.(bool) } - output, err := conn.CreateFirewallWithContext(ctx, input) + output, err := conn.CreateFirewall(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating NetworkFirewall Firewall (%s): %s", name, err) } - d.SetId(aws.StringValue(output.Firewall.FirewallArn)) + d.SetId(aws.ToString(output.Firewall.FirewallArn)) if _, err := waitFirewallCreated(ctx, conn, d.Timeout(schema.TimeoutCreate), d.Id()); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for NetworkFirewall Firewall (%s) create: %s", d.Id(), err) @@ -206,10 +206,9 @@ func resourceFirewallCreate(ctx context.Context, d *schema.ResourceData, meta in func resourceFirewallRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - - output, err := FindFirewallByARN(ctx, conn, d.Id()) + output, err := findFirewallByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] NetworkFirewall Firewall (%s) not found, removing from state", d.Id()) @@ -248,24 +247,24 @@ func resourceFirewallRead(ctx context.Context, d *schema.ResourceData, meta inte func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) updateToken := d.Get("update_token").(string) if d.HasChange("delete_protection") { input := &networkfirewall.UpdateFirewallDeleteProtectionInput{ - DeleteProtection: aws.Bool(d.Get("delete_protection").(bool)), + DeleteProtection: d.Get("delete_protection").(bool), FirewallArn: aws.String(d.Id()), UpdateToken: aws.String(updateToken), } - output, err := conn.UpdateFirewallDeleteProtectionWithContext(ctx, input) + output, err := conn.UpdateFirewallDeleteProtection(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall (%s) delete protection: %s", d.Id(), err) } - updateToken = aws.StringValue(output.UpdateToken) + updateToken = aws.ToString(output.UpdateToken) } if d.HasChange(names.AttrDescription) { @@ -275,13 +274,13 @@ func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, meta in UpdateToken: aws.String(updateToken), } - output, err := conn.UpdateFirewallDescriptionWithContext(ctx, input) + output, err := conn.UpdateFirewallDescription(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall (%s) description: %s", d.Id(), err) } - updateToken = aws.StringValue(output.UpdateToken) + updateToken = aws.ToString(output.UpdateToken) } if d.HasChange(names.AttrEncryptionConfiguration) { @@ -291,32 +290,32 @@ func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, meta in UpdateToken: aws.String(updateToken), } - output, err := conn.UpdateFirewallEncryptionConfigurationWithContext(ctx, input) + output, err := conn.UpdateFirewallEncryptionConfiguration(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall (%s) encryption configuration: %s", d.Id(), err) } - updateToken = aws.StringValue(output.UpdateToken) + updateToken = aws.ToString(output.UpdateToken) } // Note: The *_change_protection fields below are handled before their respective fields - // to account for disabling and subsequent changes + // to account for disabling and subsequent changes. if d.HasChange("firewall_policy_change_protection") { input := &networkfirewall.UpdateFirewallPolicyChangeProtectionInput{ FirewallArn: aws.String(d.Id()), - FirewallPolicyChangeProtection: aws.Bool(d.Get("firewall_policy_change_protection").(bool)), + FirewallPolicyChangeProtection: d.Get("firewall_policy_change_protection").(bool), UpdateToken: aws.String(updateToken), } - output, err := conn.UpdateFirewallPolicyChangeProtectionWithContext(ctx, input) + output, err := conn.UpdateFirewallPolicyChangeProtection(ctx, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall (%s) firewall policy change protection: %s", d.Id(), err) + return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall (%s) policy change protection: %s", d.Id(), err) } - updateToken = aws.StringValue(output.UpdateToken) + updateToken = aws.ToString(output.UpdateToken) } if d.HasChange("firewall_policy_arn") { @@ -326,29 +325,29 @@ func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, meta in UpdateToken: aws.String(updateToken), } - output, err := conn.AssociateFirewallPolicyWithContext(ctx, input) + output, err := conn.AssociateFirewallPolicy(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall (%s) firewall policy ARN: %s", d.Id(), err) } - updateToken = aws.StringValue(output.UpdateToken) + updateToken = aws.ToString(output.UpdateToken) } if d.HasChange("subnet_change_protection") { input := &networkfirewall.UpdateSubnetChangeProtectionInput{ FirewallArn: aws.String(d.Id()), - SubnetChangeProtection: aws.Bool(d.Get("subnet_change_protection").(bool)), + SubnetChangeProtection: d.Get("subnet_change_protection").(bool), UpdateToken: aws.String(updateToken), } - output, err := conn.UpdateSubnetChangeProtectionWithContext(ctx, input) + output, err := conn.UpdateSubnetChangeProtection(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Firewall (%s) subnet change protection: %s", d.Id(), err) } - updateToken = aws.StringValue(output.UpdateToken) + updateToken = aws.ToString(output.UpdateToken) } if d.HasChange("subnet_mapping") { @@ -362,35 +361,39 @@ func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, meta in UpdateToken: aws.String(updateToken), } - _, err := conn.AssociateSubnetsWithContext(ctx, input) + _, err := conn.AssociateSubnets(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "associating NetworkFirewall Firewall (%s) subnets: %s", d.Id(), err) } - updateToken, err = waitFirewallUpdated(ctx, conn, d.Timeout(schema.TimeoutUpdate), d.Id()) + output, err := waitFirewallUpdated(ctx, conn, d.Timeout(schema.TimeoutUpdate), d.Id()) if err != nil { return sdkdiag.AppendErrorf(diags, "waiting for NetworkFirewall Firewall (%s) update: %s", d.Id(), err) } + + updateToken = aws.ToString(output.UpdateToken) } if len(subnetsToRemove) > 0 { input := &networkfirewall.DisassociateSubnetsInput{ FirewallArn: aws.String(d.Id()), - SubnetIds: aws.StringSlice(subnetsToRemove), + SubnetIds: subnetsToRemove, UpdateToken: aws.String(updateToken), } - _, err := conn.DisassociateSubnetsWithContext(ctx, input) + _, err := conn.DisassociateSubnets(ctx, input) if err == nil { - /*updateToken*/ _, err = waitFirewallUpdated(ctx, conn, d.Timeout(schema.TimeoutUpdate), d.Id()) + output, err := waitFirewallUpdated(ctx, conn, d.Timeout(schema.TimeoutUpdate), d.Id()) if err != nil { return sdkdiag.AppendErrorf(diags, "waiting for NetworkFirewall Firewall (%s) update: %s", d.Id(), err) } - } else if !tfawserr.ErrMessageContains(err, networkfirewall.ErrCodeInvalidRequestException, "inaccessible") { + + updateToken = aws.ToString(output.UpdateToken) + } else if !errs.IsAErrorMessageContains[*awstypes.InvalidRequestException](err, "inaccessible") { return sdkdiag.AppendErrorf(diags, "disassociating NetworkFirewall Firewall (%s) subnets: %s", d.Id(), err) } } @@ -401,15 +404,14 @@ func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, meta in func resourceFirewallDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) log.Printf("[DEBUG] Deleting NetworkFirewall Firewall: %s", d.Id()) - _, err := conn.DeleteFirewallWithContext(ctx, &networkfirewall.DeleteFirewallInput{ + _, err := conn.DeleteFirewall(ctx, &networkfirewall.DeleteFirewallInput{ FirewallArn: aws.String(d.Id()), }) - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -424,14 +426,14 @@ func resourceFirewallDelete(ctx context.Context, d *schema.ResourceData, meta in return diags } -func FindFirewallByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeFirewallOutput, error) { +func findFirewallByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeFirewallOutput, error) { input := &networkfirewall.DescribeFirewallInput{ FirewallArn: aws.String(arn), } - output, err := conn.DescribeFirewallWithContext(ctx, input) + output, err := conn.DescribeFirewall(ctx, input) - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -449,9 +451,9 @@ func FindFirewallByARN(ctx context.Context, conn *networkfirewall.NetworkFirewal return output, nil } -func statusFirewall(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { +func statusFirewall(ctx context.Context, conn *networkfirewall.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - output, err := FindFirewallByARN(ctx, conn, arn) + output, err := findFirewallByARN(ctx, conn, arn) if tfresource.NotFound(err) { return nil, "", nil @@ -461,14 +463,14 @@ func statusFirewall(ctx context.Context, conn *networkfirewall.NetworkFirewall, return nil, "", err } - return output, aws.StringValue(output.FirewallStatus.Status), nil + return output, string(output.FirewallStatus.Status), nil } } -func waitFirewallCreated(ctx context.Context, conn *networkfirewall.NetworkFirewall, timeout time.Duration, arn string) (*networkfirewall.Firewall, error) { +func waitFirewallCreated(ctx context.Context, conn *networkfirewall.Client, timeout time.Duration, arn string) (*networkfirewall.DescribeFirewallOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{networkfirewall.FirewallStatusValueProvisioning}, - Target: []string{networkfirewall.FirewallStatusValueReady}, + Pending: enum.Slice(awstypes.FirewallStatusValueProvisioning), + Target: enum.Slice(awstypes.FirewallStatusValueReady), Refresh: statusFirewall(ctx, conn, arn), Timeout: timeout, } @@ -476,36 +478,36 @@ func waitFirewallCreated(ctx context.Context, conn *networkfirewall.NetworkFirew outputRaw, err := stateConf.WaitForStateContext(ctx) if output, ok := outputRaw.(*networkfirewall.DescribeFirewallOutput); ok { - return output.Firewall, err + return output, err } return nil, err } -func waitFirewallUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall, timeout time.Duration, arn string) (string, error) { +func waitFirewallUpdated(ctx context.Context, conn *networkfirewall.Client, timeout time.Duration, arn string) (*networkfirewall.DescribeFirewallOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{networkfirewall.FirewallStatusValueProvisioning}, - Target: []string{networkfirewall.FirewallStatusValueReady}, + Pending: enum.Slice(awstypes.FirewallStatusValueProvisioning), + Target: enum.Slice(awstypes.FirewallStatusValueReady), Refresh: statusFirewall(ctx, conn, arn), Timeout: timeout, // Delay added to account for Associate/DisassociateSubnet calls that return // a READY status immediately after the method is called instead of immediately - // returning PROVISIONING + // returning PROVISIONING. Delay: 30 * time.Second, } outputRaw, err := stateConf.WaitForStateContext(ctx) if output, ok := outputRaw.(*networkfirewall.DescribeFirewallOutput); ok { - return aws.StringValue(output.UpdateToken), err + return output, err } - return "", err + return nil, err } -func waitFirewallDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, timeout time.Duration, arn string) (*networkfirewall.Firewall, error) { +func waitFirewallDeleted(ctx context.Context, conn *networkfirewall.Client, timeout time.Duration, arn string) (*networkfirewall.DescribeFirewallOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{networkfirewall.FirewallStatusValueDeleting}, + Pending: enum.Slice(awstypes.FirewallStatusValueDeleting), Target: []string{}, Refresh: statusFirewall(ctx, conn, arn), Timeout: timeout, @@ -514,38 +516,44 @@ func waitFirewallDeleted(ctx context.Context, conn *networkfirewall.NetworkFirew outputRaw, err := stateConf.WaitForStateContext(ctx) if output, ok := outputRaw.(*networkfirewall.DescribeFirewallOutput); ok { - return output.Firewall, err + return output, err } return nil, err } -func expandSubnetMappings(l []interface{}) []*networkfirewall.SubnetMapping { - mappings := make([]*networkfirewall.SubnetMapping, 0, len(l)) - for _, tfMapRaw := range l { +func expandSubnetMappings(tfList []interface{}) []awstypes.SubnetMapping { + apiObjects := make([]awstypes.SubnetMapping, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - mapping := &networkfirewall.SubnetMapping{ + + apiObject := awstypes.SubnetMapping{ SubnetId: aws.String(tfMap[names.AttrSubnetID].(string)), } + if v, ok := tfMap[names.AttrIPAddressType].(string); ok && v != "" { - mapping.IPAddressType = aws.String(v) + apiObject.IPAddressType = awstypes.IPAddressType(v) } - mappings = append(mappings, mapping) + + apiObjects = append(apiObjects, apiObject) } - return mappings + return apiObjects } -func expandSubnetMappingIDs(l []interface{}) []string { +func expandSubnetMappingIDs(tfList []interface{}) []string { var ids []string - for _, tfMapRaw := range l { + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } + if id, ok := tfMap[names.AttrSubnetID].(string); ok && id != "" { ids = append(ids, id) } @@ -554,79 +562,66 @@ func expandSubnetMappingIDs(l []interface{}) []string { return ids } -func flattenFirewallStatus(status *networkfirewall.FirewallStatus) []interface{} { - if status == nil { +func flattenFirewallStatus(apiObject *awstypes.FirewallStatus) []interface{} { + if apiObject == nil { return nil } - m := map[string]interface{}{ - "sync_states": flattenSyncStates(status.SyncStates), + tfMap := map[string]interface{}{ + "sync_states": flattenSyncStates(apiObject.SyncStates), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenSyncStates(s map[string]*networkfirewall.SyncState) []interface{} { - if s == nil { +func flattenSyncStates(apiObject map[string]awstypes.SyncState) []interface{} { + if apiObject == nil { return nil } - syncStates := make([]interface{}, 0, len(s)) - for k, v := range s { - m := map[string]interface{}{ + tfList := make([]interface{}, 0, len(apiObject)) + + for k, v := range apiObject { + tfMap := map[string]interface{}{ names.AttrAvailabilityZone: k, "attachment": flattenSyncStateAttachment(v.Attachment), } - syncStates = append(syncStates, m) + + tfList = append(tfList, tfMap) } - return syncStates + return tfList } -func flattenSyncStateAttachment(a *networkfirewall.Attachment) []interface{} { - if a == nil { +func flattenSyncStateAttachment(apiObject *awstypes.Attachment) []interface{} { + if apiObject == nil { return nil } - m := map[string]interface{}{ - "endpoint_id": aws.StringValue(a.EndpointId), - names.AttrSubnetID: aws.StringValue(a.SubnetId), + tfMap := map[string]interface{}{ + "endpoint_id": aws.ToString(apiObject.EndpointId), + names.AttrSubnetID: aws.ToString(apiObject.SubnetId), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenSubnetMappings(sm []*networkfirewall.SubnetMapping) []interface{} { - mappings := make([]interface{}, 0, len(sm)) - for _, s := range sm { - m := map[string]interface{}{ - names.AttrSubnetID: aws.StringValue(s.SubnetId), - names.AttrIPAddressType: aws.StringValue(s.IPAddressType), - } - mappings = append(mappings, m) - } +func flattenSubnetMappings(apiObjects []awstypes.SubnetMapping) []interface{} { + tfList := make([]interface{}, 0, len(apiObjects)) - return mappings -} - -func subnetMappingsHash(v interface{}) int { - var buf bytes.Buffer + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + names.AttrIPAddressType: apiObject.IPAddressType, + names.AttrSubnetID: aws.ToString(apiObject.SubnetId), + } - tfMap, ok := v.(map[string]interface{}) - if !ok { - return 0 - } - if id, ok := tfMap[names.AttrSubnetID].(string); ok { - buf.WriteString(fmt.Sprintf("%s-", id)) - } - if id, ok := tfMap[names.AttrIPAddressType].(string); ok { - buf.WriteString(fmt.Sprintf("%s-", id)) + tfList = append(tfList, tfMap) } - return create.StringHashcode(buf.String()) + return tfList } -func subnetMappingsDiff(old, new *schema.Set) ([]string, []*networkfirewall.SubnetMapping) { +func subnetMappingsDiff(old, new *schema.Set) ([]string, []awstypes.SubnetMapping) { if old.Len() == 0 { return nil, expandSubnetMappings(new.List()) } @@ -634,6 +629,7 @@ func subnetMappingsDiff(old, new *schema.Set) ([]string, []*networkfirewall.Subn return expandSubnetMappingIDs(old.List()), nil } + subnetMappingsHash := sdkv2.SimpleSchemaSetFunc(names.AttrIPAddressType, names.AttrSubnetID) oldHashedSet := schema.NewSet(subnetMappingsHash, old.List()) newHashedSet := schema.NewSet(subnetMappingsHash, new.List()) diff --git a/internal/service/networkfirewall/firewall_test.go b/internal/service/networkfirewall/firewall_test.go index 1df937ad479..5d74130d105 100644 --- a/internal/service/networkfirewall/firewall_test.go +++ b/internal/service/networkfirewall/firewall_test.go @@ -10,7 +10,8 @@ import ( "testing" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -55,7 +56,7 @@ func TestAccNetworkFirewallFirewall_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "subnet_mapping.#", acctest.Ct1), resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_mapping.*.subnet_id", subnetResourceName, names.AttrID), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "subnet_mapping.*", map[string]string{ - names.AttrIPAddressType: networkfirewall.IPAddressTypeIpv4, + names.AttrIPAddressType: string(awstypes.IPAddressTypeIpv4), }), resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), resource.TestCheckResourceAttrSet(resourceName, "update_token"), @@ -104,7 +105,7 @@ func TestAccNetworkFirewallFirewall_dualstackSubnet(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "subnet_mapping.#", acctest.Ct1), resource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_mapping.*.subnet_id", subnetResourceName, names.AttrID), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "subnet_mapping.*", map[string]string{ - names.AttrIPAddressType: networkfirewall.IPAddressTypeDualstack, + names.AttrIPAddressType: string(awstypes.IPAddressTypeDualstack), }), resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, acctest.Ct0), resource.TestCheckResourceAttrSet(resourceName, "update_token"), @@ -433,7 +434,7 @@ func testAccCheckFirewallDestroy(ctx context.Context) resource.TestCheckFunc { continue } - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) _, err := tfnetworkfirewall.FindFirewallByARN(ctx, conn, rs.Primary.ID) @@ -459,11 +460,7 @@ func testAccCheckFirewallExists(ctx context.Context, n string) resource.TestChec return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No NetworkFirewall Firewall ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) _, err := tfnetworkfirewall.FindFirewallByARN(ctx, conn, rs.Primary.ID) @@ -472,11 +469,11 @@ func testAccCheckFirewallExists(ctx context.Context, n string) resource.TestChec } func testAccPreCheck(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) input := &networkfirewall.ListFirewallsInput{} - _, err := conn.ListFirewallsWithContext(ctx, input) + _, err := conn.ListFirewalls(ctx, input) if acctest.PreCheckSkipError(err) { t.Skipf("skipping acceptance testing: %s", err) diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 4ce6af9c080..364707b459c 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -54,7 +54,7 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { return []*types.ServicePackageSDKResource{ { - Factory: ResourceFirewall, + Factory: resourceFirewall, TypeName: "aws_networkfirewall_firewall", Name: "Firewall", Tags: &types.ServicePackageResourceTags{ From 8798de360a33c9c02dbaf7d9592807b32ee3eb73 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 11:49:38 -0400 Subject: [PATCH 60/68] d/aws_networkfirewall_firewall: Migrate to AWS SDK for Go v2. --- internal/service/networkfirewall/firewall.go | 26 ++- .../networkfirewall/firewall_data_source.go | 194 ++++++++---------- .../networkfirewall/service_package_gen.go | 4 +- 3 files changed, 108 insertions(+), 116 deletions(-) diff --git a/internal/service/networkfirewall/firewall.go b/internal/service/networkfirewall/firewall.go index 51ba55fff55..47c26c7d172 100644 --- a/internal/service/networkfirewall/firewall.go +++ b/internal/service/networkfirewall/firewall.go @@ -87,10 +87,6 @@ func resourceFirewall() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - names.AttrAvailabilityZone: { - Type: schema.TypeString, - Computed: true, - }, "attachment": { Type: schema.TypeList, Computed: true, @@ -107,6 +103,10 @@ func resourceFirewall() *schema.Resource { }, }, }, + names.AttrAvailabilityZone: { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -426,11 +426,7 @@ func resourceFirewallDelete(ctx context.Context, d *schema.ResourceData, meta in return diags } -func findFirewallByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeFirewallOutput, error) { - input := &networkfirewall.DescribeFirewallInput{ - FirewallArn: aws.String(arn), - } - +func findFirewall(ctx context.Context, conn *networkfirewall.Client, input *networkfirewall.DescribeFirewallInput) (*networkfirewall.DescribeFirewallOutput, error) { output, err := conn.DescribeFirewall(ctx, input) if errs.IsA[*awstypes.ResourceNotFoundException](err) { @@ -451,6 +447,14 @@ func findFirewallByARN(ctx context.Context, conn *networkfirewall.Client, arn st return output, nil } +func findFirewallByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeFirewallOutput, error) { + input := &networkfirewall.DescribeFirewallInput{ + FirewallArn: aws.String(arn), + } + + return findFirewall(ctx, conn, input) +} + func statusFirewall(ctx context.Context, conn *networkfirewall.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { output, err := findFirewallByARN(ctx, conn, arn) @@ -583,8 +587,8 @@ func flattenSyncStates(apiObject map[string]awstypes.SyncState) []interface{} { for k, v := range apiObject { tfMap := map[string]interface{}{ + "attachment": flattenAttachment(v.Attachment), names.AttrAvailabilityZone: k, - "attachment": flattenSyncStateAttachment(v.Attachment), } tfList = append(tfList, tfMap) @@ -593,7 +597,7 @@ func flattenSyncStates(apiObject map[string]awstypes.SyncState) []interface{} { return tfList } -func flattenSyncStateAttachment(apiObject *awstypes.Attachment) []interface{} { +func flattenAttachment(apiObject *awstypes.Attachment) []interface{} { if apiObject == nil { return nil } diff --git a/internal/service/networkfirewall/firewall_data_source.go b/internal/service/networkfirewall/firewall_data_source.go index 7c8c4de6f6c..ef2ee4f8c30 100644 --- a/internal/service/networkfirewall/firewall_data_source.go +++ b/internal/service/networkfirewall/firewall_data_source.go @@ -5,12 +5,11 @@ package networkfirewall import ( "context" - "log" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "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" @@ -21,10 +20,12 @@ import ( "github.com/hashicorp/terraform-provider-aws/names" ) -// @SDKDataSource("aws_networkfirewall_firewall") -func DataSourceFirewall() *schema.Resource { +// @SDKDataSource("aws_networkfirewall_firewall", name="Firewall") +// @Tags +func dataSourceFirewall() *schema.Resource { return &schema.Resource{ ReadWithoutTimeout: dataSourceFirewallResourceRead, + Schema: map[string]*schema.Schema{ names.AttrARN: { Type: schema.TypeString, @@ -119,10 +120,6 @@ func DataSourceFirewall() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - names.AttrAvailabilityZone: { - Type: schema.TypeString, - Computed: true, - }, "attachment": { Type: schema.TypeList, Computed: true, @@ -143,6 +140,10 @@ func DataSourceFirewall() *schema.Resource { }, }, }, + names.AttrAvailabilityZone: { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -187,181 +188,166 @@ func DataSourceFirewall() *schema.Resource { func dataSourceFirewallResourceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) input := &networkfirewall.DescribeFirewallInput{} - if v, ok := d.GetOk(names.AttrARN); ok { input.FirewallArn = aws.String(v.(string)) } - if v, ok := d.GetOk(names.AttrName); ok { input.FirewallName = aws.String(v.(string)) } - if input.FirewallArn == nil && input.FirewallName == nil { - return sdkdiag.AppendErrorf(diags, "must specify either arn, name, or both") - } - - output, err := conn.DescribeFirewallWithContext(ctx, input) - if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { - log.Printf("[WARN] NetworkFirewall Firewall (%s) not found, removing from state", d.Id()) - d.SetId("") - return diags - } + output, err := findFirewall(ctx, conn, input) if err != nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Firewall (%s): %s", d.Id(), err) - } - - if output == nil || output.Firewall == nil { - return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Firewall (%s): empty output", d.Id()) + return sdkdiag.AppendErrorf(diags, "reading NetworkFirewall Firewall: %s", err) } firewall := output.Firewall - + d.SetId(aws.ToString(firewall.FirewallArn)) d.Set(names.AttrARN, firewall.FirewallArn) d.Set("delete_protection", firewall.DeleteProtection) d.Set(names.AttrDescription, firewall.Description) - d.Set(names.AttrName, firewall.FirewallName) - d.Set(names.AttrEncryptionConfiguration, flattenDataSourceEncryptionConfiguration(firewall.EncryptionConfiguration)) + if err := d.Set(names.AttrEncryptionConfiguration, flattenDataSourceEncryptionConfiguration(firewall.EncryptionConfiguration)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting encryption_configuration: %s", err) + } d.Set("firewall_policy_arn", firewall.FirewallPolicyArn) d.Set("firewall_policy_change_protection", firewall.FirewallPolicyChangeProtection) - d.Set("firewall_status", flattenDataSourceFirewallStatus(output.FirewallStatus)) + if err := d.Set("firewall_status", flattenDataSourceFirewallStatus(output.FirewallStatus)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting firewall_status: %s", err) + } + d.Set(names.AttrName, firewall.FirewallName) d.Set("subnet_change_protection", firewall.SubnetChangeProtection) - d.Set("update_token", output.UpdateToken) - d.Set(names.AttrVPCID, firewall.VpcId) - if err := d.Set("subnet_mapping", flattenDataSourceSubnetMappings(firewall.SubnetMappings)); err != nil { return sdkdiag.AppendErrorf(diags, "setting subnet_mappings: %s", err) } + d.Set("update_token", output.UpdateToken) + d.Set(names.AttrVPCID, firewall.VpcId) - if err := d.Set(names.AttrTags, KeyValueTags(ctx, firewall.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return sdkdiag.AppendErrorf(diags, "setting tags: %s", err) - } - - d.SetId(aws.StringValue(firewall.FirewallArn)) + setTagsOut(ctx, firewall.Tags) return diags } -func flattenDataSourceFirewallStatus(status *networkfirewall.FirewallStatus) []interface{} { - if status == nil { +func flattenDataSourceFirewallStatus(apiObject *awstypes.FirewallStatus) []interface{} { + if apiObject == nil { return nil } - m := map[string]interface{}{} - if status.CapacityUsageSummary != nil { - m["capacity_usage_summary"] = flattenDataSourceCapacityUsageSummary(status.CapacityUsageSummary) - } - if status.ConfigurationSyncStateSummary != nil { - m["configuration_sync_state_summary"] = aws.StringValue(status.ConfigurationSyncStateSummary) + + tfMap := map[string]interface{}{ + "configuration_sync_state_summary": apiObject.ConfigurationSyncStateSummary, + names.AttrStatus: apiObject.Status, } - if status.Status != nil { - m[names.AttrStatus] = aws.StringValue(status.Status) + + if apiObject.CapacityUsageSummary != nil { + tfMap["capacity_usage_summary"] = flattenDataSourceCapacityUsageSummary(apiObject.CapacityUsageSummary) } - if status.SyncStates != nil { - m["sync_states"] = flattenDataSourceSyncStates(status.SyncStates) + if apiObject.SyncStates != nil { + tfMap["sync_states"] = flattenDataSourceSyncStates(apiObject.SyncStates) } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenDataSourceCapacityUsageSummary(state *networkfirewall.CapacityUsageSummary) []interface{} { - if state == nil { +func flattenDataSourceCapacityUsageSummary(apiObject *awstypes.CapacityUsageSummary) []interface{} { + if apiObject == nil { return nil } - m := map[string]interface{}{ - "cidrs": flattenDataSourceCIDRSummary(state.CIDRs), + tfMap := map[string]interface{}{ + "cidrs": flattenDataSourceCIDRSummary(apiObject.CIDRs), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenDataSourceCIDRSummary(state *networkfirewall.CIDRSummary) []interface{} { - if state == nil { +func flattenDataSourceCIDRSummary(apiObject *awstypes.CIDRSummary) []interface{} { + if apiObject == nil { return nil } - m := map[string]interface{}{ - "available_cidr_count": int(aws.Int64Value(state.AvailableCIDRCount)), - "ip_set_references": flattenDataSourceIPSetReferences(state.IPSetReferences), - "utilized_cidr_count": int(aws.Int64Value(state.UtilizedCIDRCount)), + tfMap := map[string]interface{}{ + "available_cidr_count": aws.ToInt32(apiObject.AvailableCIDRCount), + "ip_set_references": flattenDataSourceIPSetReferences(apiObject.IPSetReferences), + "utilized_cidr_count": aws.ToInt32(apiObject.UtilizedCIDRCount), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenDataSourceIPSetReferences(state map[string]*networkfirewall.IPSetMetadata) []interface{} { - if state == nil { +func flattenDataSourceIPSetReferences(apiObject map[string]awstypes.IPSetMetadata) []interface{} { + if apiObject == nil { return nil } - ipSetReferences := make([]interface{}, 0, len(state)) - for _, v := range state { - m := map[string]interface{}{ - "resolved_cidr_count": int(aws.Int64Value(v.ResolvedCIDRCount)), - } - ipSetReferences = append(ipSetReferences, m) + tfList := make([]interface{}, 0, len(apiObject)) + + for _, v := range apiObject { + tfList = append(tfList, map[string]interface{}{ + "resolved_cidr_count": aws.ToInt32(v.ResolvedCIDRCount), + }) } - return ipSetReferences + return tfList } -func flattenDataSourceSyncStates(state map[string]*networkfirewall.SyncState) []interface{} { - if state == nil { +func flattenDataSourceSyncStates(apiObject map[string]awstypes.SyncState) []interface{} { + if apiObject == nil { return nil } - syncStates := make([]interface{}, 0, len(state)) - for k, v := range state { - m := map[string]interface{}{ + tfList := make([]interface{}, 0, len(apiObject)) + + for k, v := range apiObject { + tfMap := map[string]interface{}{ + "attachment": flattenDataSourceAttachment(v.Attachment), names.AttrAvailabilityZone: k, - "attachment": flattenDataSourceSyncStateAttachment(v.Attachment), } - syncStates = append(syncStates, m) + + tfList = append(tfList, tfMap) } - return syncStates + return tfList } -func flattenDataSourceSyncStateAttachment(attach *networkfirewall.Attachment) []interface{} { - if attach == nil { +func flattenDataSourceAttachment(apiObject *awstypes.Attachment) []interface{} { + if apiObject == nil { return nil } - m := map[string]interface{}{ - "endpoint_id": aws.StringValue(attach.EndpointId), - names.AttrStatus: aws.StringValue(attach.Status), - names.AttrSubnetID: aws.StringValue(attach.SubnetId), + tfMap := map[string]interface{}{ + "endpoint_id": aws.ToString(apiObject.EndpointId), + names.AttrStatus: apiObject.Status, + names.AttrSubnetID: aws.ToString(apiObject.SubnetId), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenDataSourceSubnetMappings(subnet []*networkfirewall.SubnetMapping) []interface{} { - mappings := make([]interface{}, 0, len(subnet)) - for _, s := range subnet { - m := map[string]interface{}{ - names.AttrSubnetID: aws.StringValue(s.SubnetId), +func flattenDataSourceSubnetMappings(apiObjects []awstypes.SubnetMapping) []interface{} { + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, s := range apiObjects { + tfMap := map[string]interface{}{ + names.AttrSubnetID: aws.ToString(s.SubnetId), } - mappings = append(mappings, m) + + tfList = append(tfList, tfMap) } - return mappings + return tfList } -func flattenDataSourceEncryptionConfiguration(encrypt *networkfirewall.EncryptionConfiguration) []interface{} { - if encrypt == nil { +func flattenDataSourceEncryptionConfiguration(apiObject *awstypes.EncryptionConfiguration) []interface{} { + if apiObject == nil { return nil } - m := map[string]interface{}{ - names.AttrKeyID: aws.StringValue(encrypt.KeyId), - names.AttrType: aws.StringValue(encrypt.Type), + tfMap := map[string]interface{}{ + names.AttrKeyID: aws.ToString(apiObject.KeyId), + names.AttrType: apiObject.Type, } - return []interface{}{m} + return []interface{}{tfMap} } diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 364707b459c..3ced3bcdff1 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -34,8 +34,10 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { return []*types.ServicePackageSDKDataSource{ { - Factory: DataSourceFirewall, + Factory: dataSourceFirewall, TypeName: "aws_networkfirewall_firewall", + Name: "Firewall", + Tags: &types.ServicePackageResourceTags{}, }, { Factory: dataSourceFirewallPolicy, From bda2dd1cc106416ac10ea47a4f460f2e58fff62e Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 13:37:53 -0400 Subject: [PATCH 61/68] r/aws_networkfirewall_rule_group: Migrate to AWS SDK for Go v2. --- .../service/networkfirewall/exports_test.go | 2 + .../service/networkfirewall/rule_group.go | 1420 +++++++++-------- .../networkfirewall/rule_group_test.go | 117 +- .../networkfirewall/service_package_gen.go | 2 +- 4 files changed, 805 insertions(+), 736 deletions(-) diff --git a/internal/service/networkfirewall/exports_test.go b/internal/service/networkfirewall/exports_test.go index 4711dcfac7c..ec40d5ef6b7 100644 --- a/internal/service/networkfirewall/exports_test.go +++ b/internal/service/networkfirewall/exports_test.go @@ -9,11 +9,13 @@ var ( ResourceFirewallPolicy = resourceFirewallPolicy ResourceLoggingConfiguration = resourceLoggingConfiguration ResourceResourcePolicy = resourceResourcePolicy + ResourceRuleGroup = resourceRuleGroup ResourceTLSInspectionConfiguration = newTLSInspectionConfigurationResource FindFirewallByARN = findFirewallByARN FindFirewallPolicyByARN = findFirewallPolicyByARN FindLoggingConfigurationByARN = findLoggingConfigurationByARN FindResourcePolicyByARN = findResourcePolicyByARN + FindRuleGroupByARN = findRuleGroupByARN FindTLSInspectionConfigurationByARN = findTLSInspectionConfigurationByARN ) diff --git a/internal/service/networkfirewall/rule_group.go b/internal/service/networkfirewall/rule_group.go index 8a8e441054e..5b775b65e4f 100644 --- a/internal/service/networkfirewall/rule_group.go +++ b/internal/service/networkfirewall/rule_group.go @@ -9,15 +9,17 @@ import ( "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "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/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" @@ -28,7 +30,7 @@ import ( // @SDKResource("aws_networkfirewall_rule_group", name="Rule Group") // @Tags(identifierAttribute="id") -func ResourceRuleGroup() *schema.Resource { +func resourceRuleGroup() *schema.Resource { return &schema.Resource{ CreateWithoutTimeout: resourceRuleGroupCreate, ReadWithoutTimeout: resourceRuleGroupRead, @@ -39,290 +41,292 @@ func ResourceRuleGroup() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, - Schema: map[string]*schema.Schema{ - names.AttrARN: { - Type: schema.TypeString, - Computed: true, - }, - "capacity": { - Type: schema.TypeInt, - Required: true, - ForceNew: true, - }, - names.AttrDescription: { - Type: schema.TypeString, - Optional: true, - }, - names.AttrEncryptionConfiguration: encryptionConfigurationSchema(), - names.AttrName: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "rule_group": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "reference_sets": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ip_set_references": { - Type: schema.TypeSet, - Optional: true, - MaxItems: 5, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ip_set_reference": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "reference_arn": { - Type: schema.TypeString, - Required: true, - ValidateFunc: verify.ValidARN, + SchemaFunc: func() map[string]*schema.Schema { + return map[string]*schema.Schema{ + names.AttrARN: { + Type: schema.TypeString, + Computed: true, + }, + "capacity": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + }, + names.AttrDescription: { + Type: schema.TypeString, + Optional: true, + }, + names.AttrEncryptionConfiguration: encryptionConfigurationSchema(), + names.AttrName: { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "rule_group": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "reference_sets": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_set_references": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 5, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_set_reference": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "reference_arn": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidARN, + }, }, }, }, - }, - names.AttrKey: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 32), - validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), - validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), - ), + names.AttrKey: { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 32), + validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), + validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), + ), + }, }, }, }, }, }, }, - }, - "rules_source": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "rules_source_list": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "generated_rules_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.GeneratedRulesType_Values(), false), - }, - "target_types": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice(networkfirewall.TargetType_Values(), false), + "rules_source": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rules_source_list": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "generated_rules_type": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.GeneratedRulesType](), + }, + "target_types": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.TargetType](), + }, + }, + "targets": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, - }, - "targets": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, - }, - "rules_string": { - Type: schema.TypeString, - Optional: true, - }, - "stateful_rule": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrAction: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.StatefulAction_Values(), false), - }, - names.AttrHeader: { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrDestination: { - Type: schema.TypeString, - Required: true, - }, - "destination_port": { - Type: schema.TypeString, - Required: true, - }, - "direction": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.StatefulRuleDirection_Values(), false), - }, - names.AttrProtocol: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.StatefulRuleProtocol_Values(), false), - }, - names.AttrSource: { - Type: schema.TypeString, - Required: true, - }, - "source_port": { - Type: schema.TypeString, - Required: true, + "rules_string": { + Type: schema.TypeString, + Optional: true, + }, + "stateful_rule": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrAction: { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.StatefulAction](), + }, + names.AttrHeader: { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrDestination: { + Type: schema.TypeString, + Required: true, + }, + "destination_port": { + Type: schema.TypeString, + Required: true, + }, + "direction": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.StatefulRuleDirection](), + }, + names.AttrProtocol: { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.StatefulRuleProtocol](), + }, + names.AttrSource: { + Type: schema.TypeString, + Required: true, + }, + "source_port": { + Type: schema.TypeString, + Required: true, + }, }, }, }, - }, - "rule_option": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "keyword": { - Type: schema.TypeString, - Required: true, - }, - "settings": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + "rule_option": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "keyword": { + Type: schema.TypeString, + Required: true, + }, + "settings": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, }, }, }, }, }, - }, - "stateless_rules_and_custom_actions": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "custom_action": customActionSchema(), - "stateless_rule": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrPriority: { - Type: schema.TypeInt, - Required: true, - }, - "rule_definition": { - Type: schema.TypeList, - MaxItems: 1, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrActions: { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "match_attributes": { - Type: schema.TypeList, - MaxItems: 1, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrDestination: { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "address_definition": { - Type: schema.TypeString, - Required: true, - ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, + "stateless_rules_and_custom_actions": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "custom_action": customActionSchema(), + "stateless_rule": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrPriority: { + Type: schema.TypeInt, + Required: true, + }, + "rule_definition": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrActions: { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "match_attributes": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrDestination: { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address_definition": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, + }, }, }, }, - }, - "destination_port": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "from_port": { - Type: schema.TypeInt, - Required: true, - }, - "to_port": { - Type: schema.TypeInt, - Optional: true, + "destination_port": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "from_port": { + Type: schema.TypeInt, + Required: true, + }, + "to_port": { + Type: schema.TypeInt, + Optional: true, + }, }, }, }, - }, - "protocols": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeInt}, - }, - names.AttrSource: { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "address_definition": { - Type: schema.TypeString, - Required: true, - ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, + "protocols": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeInt}, + }, + names.AttrSource: { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address_definition": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidIPv4CIDRNetworkAddress, + }, }, }, }, - }, - "source_port": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "from_port": { - Type: schema.TypeInt, - Required: true, - }, - "to_port": { - Type: schema.TypeInt, - Optional: true, + "source_port": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "from_port": { + Type: schema.TypeInt, + Required: true, + }, + "to_port": { + Type: schema.TypeInt, + Optional: true, + }, }, }, }, - }, - "tcp_flag": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "flags": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice(networkfirewall.TCPFlag_Values(), false), + "tcp_flag": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "flags": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.TCPFlag](), + }, }, - }, - "masks": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice(networkfirewall.TCPFlag_Values(), false), + "masks": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: enum.Validate[awstypes.TCPFlag](), + }, }, }, }, @@ -342,68 +346,68 @@ func ResourceRuleGroup() *schema.Resource { }, }, }, - }, - "rule_variables": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ip_sets": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrKey: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 32), - validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), - validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), - ), - }, - "ip_set": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "definition": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + "rule_variables": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_sets": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrKey: { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 32), + validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), + validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), + ), + }, + "ip_set": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "definition": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, }, }, }, }, }, - }, - "port_sets": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - names.AttrKey: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 32), - validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), - validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), - ), - }, - "port_set": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "definition": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + "port_sets": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + names.AttrKey: { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 32), + validation.StringMatch(regexache.MustCompile(`^[A-Za-z]`), "must begin with alphabetic character"), + validation.StringMatch(regexache.MustCompile(`^[0-9A-Za-z_]+$`), "must contain only alphanumeric and underscore characters"), + ), + }, + "port_set": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "definition": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, }, }, @@ -413,39 +417,39 @@ func ResourceRuleGroup() *schema.Resource { }, }, }, - }, - "stateful_rule_options": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "rule_order": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.RuleOrder_Values(), false), + "stateful_rule_options": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rule_order": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.RuleOrder](), + }, }, }, }, }, }, }, - }, - "rules": { - Type: schema.TypeString, - Optional: true, - }, - names.AttrTags: tftags.TagsSchema(), - names.AttrTagsAll: tftags.TagsSchemaComputed(), - names.AttrType: { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice(networkfirewall.RuleGroupType_Values(), false), - }, - "update_token": { - Type: schema.TypeString, - Computed: true, - }, + "rules": { + Type: schema.TypeString, + Optional: true, + }, + names.AttrTags: tftags.TagsSchema(), + names.AttrTagsAll: tftags.TagsSchemaComputed(), + names.AttrType: { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: enum.Validate[awstypes.RuleGroupType](), + }, + "update_token": { + Type: schema.TypeString, + Computed: true, + }, + } }, CustomizeDiff: customdiff.Sequence( @@ -461,15 +465,14 @@ func ResourceRuleGroup() *schema.Resource { func resourceRuleGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) name := d.Get(names.AttrName).(string) input := &networkfirewall.CreateRuleGroupInput{ - Capacity: aws.Int64(int64(d.Get("capacity").(int))), + Capacity: aws.Int32(int32(d.Get("capacity").(int))), RuleGroupName: aws.String(name), Tags: getTagsIn(ctx), - Type: aws.String(d.Get(names.AttrType).(string)), + Type: awstypes.RuleGroupType(d.Get(names.AttrType).(string)), } if v, ok := d.GetOk(names.AttrDescription); ok { @@ -488,27 +491,22 @@ func resourceRuleGroupCreate(ctx context.Context, d *schema.ResourceData, meta i input.Rules = aws.String(v.(string)) } - output, err := conn.CreateRuleGroupWithContext(ctx, input) + output, err := conn.CreateRuleGroup(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating NetworkFirewall Rule Group (%s): %s", name, err) } - d.SetId(aws.StringValue(output.RuleGroupResponse.RuleGroupArn)) + d.SetId(aws.ToString(output.RuleGroupResponse.RuleGroupArn)) return append(diags, resourceRuleGroupRead(ctx, d, meta)...) } func resourceRuleGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - - output, err := FindRuleGroupByARN(ctx, conn, d.Id()) - - if err == nil && output.RuleGroup == nil { - err = tfresource.NewEmptyResultError(d.Id()) - } + output, err := findRuleGroupByARN(ctx, conn, d.Id()) if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] NetworkFirewall Rule Group (%s) not found, removing from state", d.Id()) @@ -524,7 +522,9 @@ func resourceRuleGroupRead(ctx context.Context, d *schema.ResourceData, meta int d.Set(names.AttrARN, response.RuleGroupArn) d.Set("capacity", response.Capacity) d.Set(names.AttrDescription, response.Description) - d.Set(names.AttrEncryptionConfiguration, flattenEncryptionConfiguration(response.EncryptionConfiguration)) + if err := d.Set(names.AttrEncryptionConfiguration, flattenEncryptionConfiguration(response.EncryptionConfiguration)); err != nil { + return sdkdiag.AppendErrorf(diags, "setting encryption_configuration: %s", err) + } d.Set(names.AttrName, response.RuleGroupName) if err := d.Set("rule_group", flattenRuleGroup(output.RuleGroup)); err != nil { return sdkdiag.AppendErrorf(diags, "setting rule_group: %s", err) @@ -539,14 +539,13 @@ func resourceRuleGroupRead(ctx context.Context, d *schema.ResourceData, meta int func resourceRuleGroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) if d.HasChanges(names.AttrDescription, names.AttrEncryptionConfiguration, "rule_group", "rules", names.AttrType) { input := &networkfirewall.UpdateRuleGroupInput{ EncryptionConfiguration: expandEncryptionConfiguration(d.Get(names.AttrEncryptionConfiguration).([]interface{})), RuleGroupArn: aws.String(d.Id()), - Type: aws.String(d.Get(names.AttrType).(string)), + Type: awstypes.RuleGroupType(d.Get(names.AttrType).(string)), UpdateToken: aws.String(d.Get("update_token").(string)), } @@ -577,7 +576,7 @@ func resourceRuleGroupUpdate(ctx context.Context, d *schema.ResourceData, meta i } } - _, err := conn.UpdateRuleGroupWithContext(ctx, input) + _, err := conn.UpdateRuleGroup(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "updating NetworkFirewall Rule Group (%s): %s", d.Id(), err) @@ -589,20 +588,19 @@ func resourceRuleGroupUpdate(ctx context.Context, d *schema.ResourceData, meta i func resourceRuleGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).NetworkFirewallClient(ctx) + log.Printf("[DEBUG] Deleting NetworkFirewall Rule Group: %s", d.Id()) const ( timeout = 10 * time.Minute ) - conn := meta.(*conns.AWSClient).NetworkFirewallConn(ctx) - - log.Printf("[DEBUG] Deleting NetworkFirewall Rule Group: %s", d.Id()) - _, err := tfresource.RetryWhenAWSErrMessageContains(ctx, timeout, func() (interface{}, error) { - return conn.DeleteRuleGroupWithContext(ctx, &networkfirewall.DeleteRuleGroupInput{ + _, err := tfresource.RetryWhenIsAErrorMessageContains[*awstypes.InvalidOperationException](ctx, timeout, func() (interface{}, error) { + return conn.DeleteRuleGroup(ctx, &networkfirewall.DeleteRuleGroupInput{ RuleGroupArn: aws.String(d.Id()), }) - }, networkfirewall.ErrCodeInvalidOperationException, "Unable to delete the object because it is still in use") + }, "Unable to delete the object because it is still in use") - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return diags } @@ -617,14 +615,14 @@ func resourceRuleGroupDelete(ctx context.Context, d *schema.ResourceData, meta i return diags } -func FindRuleGroupByARN(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) (*networkfirewall.DescribeRuleGroupOutput, error) { +func findRuleGroupByARN(ctx context.Context, conn *networkfirewall.Client, arn string) (*networkfirewall.DescribeRuleGroupOutput, error) { input := &networkfirewall.DescribeRuleGroupInput{ RuleGroupArn: aws.String(arn), } - output, err := conn.DescribeRuleGroupWithContext(ctx, input) + output, err := conn.DescribeRuleGroup(ctx, input) - if tfawserr.ErrCodeEquals(err, networkfirewall.ErrCodeResourceNotFoundException) { + if errs.IsA[*awstypes.ResourceNotFoundException](err) { return nil, &retry.NotFoundError{ LastError: err, LastRequest: input, @@ -635,16 +633,16 @@ func FindRuleGroupByARN(ctx context.Context, conn *networkfirewall.NetworkFirewa return nil, err } - if output == nil || output.RuleGroupResponse == nil { + if output == nil || output.RuleGroup == nil || output.RuleGroupResponse == nil { return nil, tfresource.NewEmptyResultError(input) } return output, nil } -func statusRuleGroup(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string) retry.StateRefreshFunc { +func statusRuleGroup(ctx context.Context, conn *networkfirewall.Client, arn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - output, err := FindRuleGroupByARN(ctx, conn, arn) + output, err := findRuleGroupByARN(ctx, conn, arn) if tfresource.NotFound(err) { return nil, "", nil @@ -654,13 +652,13 @@ func statusRuleGroup(ctx context.Context, conn *networkfirewall.NetworkFirewall, return nil, "", err } - return output.RuleGroup, aws.StringValue(output.RuleGroupResponse.RuleGroupStatus), nil + return output.RuleGroup, string(output.RuleGroupResponse.RuleGroupStatus), nil } } -func waitRuleGroupDeleted(ctx context.Context, conn *networkfirewall.NetworkFirewall, arn string, timeout time.Duration) (*networkfirewall.RuleGroup, error) { +func waitRuleGroupDeleted(ctx context.Context, conn *networkfirewall.Client, arn string, timeout time.Duration) (*networkfirewall.DescribeRuleGroupOutput, error) { stateConf := &retry.StateChangeConf{ - Pending: []string{networkfirewall.ResourceStatusDeleting}, + Pending: enum.Slice(awstypes.ResourceStatusDeleting), Target: []string{}, Refresh: statusRuleGroup(ctx, conn, arn), Timeout: timeout, @@ -668,685 +666,757 @@ func waitRuleGroupDeleted(ctx context.Context, conn *networkfirewall.NetworkFire outputRaw, err := stateConf.WaitForStateContext(ctx) - if output, ok := outputRaw.(*networkfirewall.RuleGroup); ok { + if output, ok := outputRaw.(*networkfirewall.DescribeRuleGroupOutput); ok { return output, err } return nil, err } -func expandStatefulRuleHeader(l []interface{}) *networkfirewall.Header { - if len(l) == 0 || l[0] == nil { +func expandStatefulRuleHeader(tfList []interface{}) *awstypes.Header { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - header := &networkfirewall.Header{} + + apiObject := &awstypes.Header{} + if v, ok := tfMap[names.AttrDestination].(string); ok && v != "" { - header.Destination = aws.String(v) + apiObject.Destination = aws.String(v) } if v, ok := tfMap["destination_port"].(string); ok && v != "" { - header.DestinationPort = aws.String(v) + apiObject.DestinationPort = aws.String(v) } if v, ok := tfMap["direction"].(string); ok && v != "" { - header.Direction = aws.String(v) + apiObject.Direction = awstypes.StatefulRuleDirection(v) } if v, ok := tfMap[names.AttrProtocol].(string); ok && v != "" { - header.Protocol = aws.String(v) + apiObject.Protocol = awstypes.StatefulRuleProtocol(v) } if v, ok := tfMap[names.AttrSource].(string); ok && v != "" { - header.Source = aws.String(v) + apiObject.Source = aws.String(v) } if v, ok := tfMap["source_port"].(string); ok && v != "" { - header.SourcePort = aws.String(v) + apiObject.SourcePort = aws.String(v) } - return header + return apiObject } -func expandStatefulRuleOptions(l []interface{}) []*networkfirewall.RuleOption { - if len(l) == 0 || l[0] == nil { +func expandStatefulRuleOptions(tfList []interface{}) []awstypes.RuleOption { + if len(tfList) == 0 || tfList[0] == nil { return nil } - ruleOptions := make([]*networkfirewall.RuleOption, 0, len(l)) - for _, tfMapRaw := range l { + apiObjects := make([]awstypes.RuleOption, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - keyword := tfMap["keyword"].(string) - option := &networkfirewall.RuleOption{ - Keyword: aws.String(keyword), + + apiObject := awstypes.RuleOption{ + Keyword: aws.String(tfMap["keyword"].(string)), } + if v, ok := tfMap["settings"].(*schema.Set); ok && v.Len() > 0 { - option.Settings = flex.ExpandStringSet(v) + apiObject.Settings = flex.ExpandStringValueSet(v) } - ruleOptions = append(ruleOptions, option) + + apiObjects = append(apiObjects, apiObject) } - return ruleOptions + return apiObjects } -func expandRulesSourceList(l []interface{}) *networkfirewall.RulesSourceList { - if len(l) == 0 || l[0] == nil { +func expandRulesSourceList(tfList []interface{}) *awstypes.RulesSourceList { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - rulesSourceList := &networkfirewall.RulesSourceList{} + + apiObject := &awstypes.RulesSourceList{} + if v, ok := tfMap["generated_rules_type"].(string); ok && v != "" { - rulesSourceList.GeneratedRulesType = aws.String(v) + apiObject.GeneratedRulesType = awstypes.GeneratedRulesType(v) } if v, ok := tfMap["target_types"].(*schema.Set); ok && v.Len() > 0 { - rulesSourceList.TargetTypes = flex.ExpandStringSet(v) + apiObject.TargetTypes = flex.ExpandStringyValueSet[awstypes.TargetType](v) } if v, ok := tfMap["targets"].(*schema.Set); ok && v.Len() > 0 { - rulesSourceList.Targets = flex.ExpandStringSet(v) + apiObject.Targets = flex.ExpandStringValueSet(v) } - return rulesSourceList + return apiObject } -func expandStatefulRules(l []interface{}) []*networkfirewall.StatefulRule { - if len(l) == 0 || l[0] == nil { +func expandStatefulRules(tfList []interface{}) []awstypes.StatefulRule { + if len(tfList) == 0 || tfList[0] == nil { return nil } - rules := make([]*networkfirewall.StatefulRule, 0, len(l)) - for _, tfMapRaw := range l { + apiObjects := make([]awstypes.StatefulRule, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - rule := &networkfirewall.StatefulRule{} + + apiObject := awstypes.StatefulRule{} + if v, ok := tfMap[names.AttrAction].(string); ok && v != "" { - rule.Action = aws.String(v) + apiObject.Action = awstypes.StatefulAction(v) } if v, ok := tfMap[names.AttrHeader].([]interface{}); ok && len(v) > 0 && v[0] != nil { - rule.Header = expandStatefulRuleHeader(v) + apiObject.Header = expandStatefulRuleHeader(v) } if v, ok := tfMap["rule_option"].(*schema.Set); ok && v.Len() > 0 { - rule.RuleOptions = expandStatefulRuleOptions(v.List()) + apiObject.RuleOptions = expandStatefulRuleOptions(v.List()) } - rules = append(rules, rule) + + apiObjects = append(apiObjects, apiObject) } - return rules + return apiObjects } -func expandRuleGroup(tfMap map[string]interface{}) *networkfirewall.RuleGroup { +func expandRuleGroup(tfMap map[string]interface{}) *awstypes.RuleGroup { if tfMap == nil { return nil } - ruleGroup := &networkfirewall.RuleGroup{} - if tfList, ok := tfMap["reference_sets"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { - referenceSets := &networkfirewall.ReferenceSets{} - rvMap, ok := tfList[0].(map[string]interface{}) - if ok { - if v, ok := rvMap["ip_set_references"].(*schema.Set); ok && v.Len() > 0 { + apiObject := &awstypes.RuleGroup{} + + if v, ok := tfMap["reference_sets"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + if tfMap, ok := v[0].(map[string]interface{}); ok { + referenceSets := &awstypes.ReferenceSets{} + + if v, ok := tfMap["ip_set_references"].(*schema.Set); ok && v.Len() > 0 { referenceSets.IPSetReferences = expandIPSetReferences(v.List()) } - ruleGroup.ReferenceSets = referenceSets + apiObject.ReferenceSets = referenceSets } } - if tfList, ok := tfMap["rule_variables"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { - ruleVariables := &networkfirewall.RuleVariables{} - rvMap, ok := tfList[0].(map[string]interface{}) - if ok { - if v, ok := rvMap["ip_sets"].(*schema.Set); ok && v.Len() > 0 { + + if v, ok := tfMap["rule_variables"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + if tfMap, ok := v[0].(map[string]interface{}); ok { + ruleVariables := &awstypes.RuleVariables{} + + if v, ok := tfMap["ip_sets"].(*schema.Set); ok && v.Len() > 0 { ruleVariables.IPSets = expandIPSets(v.List()) } - if v, ok := rvMap["port_sets"].(*schema.Set); ok && v.Len() > 0 { + if v, ok := tfMap["port_sets"].(*schema.Set); ok && v.Len() > 0 { ruleVariables.PortSets = expandPortSets(v.List()) } - ruleGroup.RuleVariables = ruleVariables + + apiObject.RuleVariables = ruleVariables } } - if tfList, ok := tfMap["rules_source"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { - rulesSource := &networkfirewall.RulesSource{} - rsMap, ok := tfList[0].(map[string]interface{}) - if ok { - if v, ok := rsMap["rules_source_list"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + + if v, ok := tfMap["rules_source"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + if tfMap, ok := v[0].(map[string]interface{}); ok { + rulesSource := &awstypes.RulesSource{} + + if v, ok := tfMap["rules_source_list"].([]interface{}); ok && len(v) > 0 && v[0] != nil { rulesSource.RulesSourceList = expandRulesSourceList(v) } - if v, ok := rsMap["rules_string"].(string); ok && v != "" { + if v, ok := tfMap["rules_string"].(string); ok && v != "" { rulesSource.RulesString = aws.String(v) } - if v, ok := rsMap["stateful_rule"].([]interface{}); ok && len(v) > 0 { + if v, ok := tfMap["stateful_rule"].([]interface{}); ok && len(v) > 0 { rulesSource.StatefulRules = expandStatefulRules(v) } - if v, ok := rsMap["stateless_rules_and_custom_actions"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + if v, ok := tfMap["stateless_rules_and_custom_actions"].([]interface{}); ok && len(v) > 0 && v[0] != nil { rulesSource.StatelessRulesAndCustomActions = expandStatelessRulesAndCustomActions(v) } - ruleGroup.RulesSource = rulesSource + + apiObject.RulesSource = rulesSource } } - if tfList, ok := tfMap["stateful_rule_options"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { - statefulRuleOptions := &networkfirewall.StatefulRuleOptions{} - sroMap, ok := tfList[0].(map[string]interface{}) - if ok { - if v, ok := sroMap["rule_order"].(string); ok && v != "" { - statefulRuleOptions.RuleOrder = aws.String(v) + + if v, ok := tfMap["stateful_rule_options"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + if tfMap, ok := v[0].(map[string]interface{}); ok { + statefulRuleOptions := &awstypes.StatefulRuleOptions{} + + if v, ok := tfMap["rule_order"].(string); ok && v != "" { + statefulRuleOptions.RuleOrder = awstypes.RuleOrder(v) } + + apiObject.StatefulRuleOptions = statefulRuleOptions } - ruleGroup.StatefulRuleOptions = statefulRuleOptions } - return ruleGroup + return apiObject } -func expandIPSetReferences(l []interface{}) map[string]*networkfirewall.IPSetReference { - if len(l) == 0 || l[0] == nil { +func expandIPSetReferences(tfList []interface{}) map[string]awstypes.IPSetReference { + if len(tfList) == 0 || tfList[0] == nil { return nil } - m := make(map[string]*networkfirewall.IPSetReference) - for _, tfMapRaw := range l { + apiObject := make(map[string]awstypes.IPSetReference) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - if key, ok := tfMap[names.AttrKey].(string); ok && key != "" { - if tfList, ok := tfMap["ip_set_reference"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { - tfMap, ok := tfList[0].(map[string]interface{}) - if ok { - if tfSet, ok := tfMap["reference_arn"].(string); ok && tfSet != "" { - ipSetReference := &networkfirewall.IPSetReference{ - ReferenceArn: aws.String(tfSet), + if k, ok := tfMap[names.AttrKey].(string); ok && k != "" { + if v, ok := tfMap["ip_set_reference"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + if tfMap, ok := v[0].(map[string]interface{}); ok { + if v, ok := tfMap["reference_arn"].(string); ok && v != "" { + apiObject[k] = awstypes.IPSetReference{ + ReferenceArn: aws.String(v), } - m[key] = ipSetReference } } } } } - return m + return apiObject } -func expandPortSets(l []interface{}) map[string]*networkfirewall.PortSet { - if len(l) == 0 || l[0] == nil { +func expandPortSets(tfList []interface{}) map[string]awstypes.PortSet { + if len(tfList) == 0 || tfList[0] == nil { return nil } - m := make(map[string]*networkfirewall.PortSet) - for _, tfMapRaw := range l { + apiObject := make(map[string]awstypes.PortSet) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - if key, ok := tfMap[names.AttrKey].(string); ok && key != "" { - if tfList, ok := tfMap["port_set"].([]interface{}); ok && len(tfList) > 0 && tfList[0] != nil { - tfMap, ok := tfList[0].(map[string]interface{}) - if ok { - if tfSet, ok := tfMap["definition"].(*schema.Set); ok && tfSet.Len() > 0 { - ipSet := &networkfirewall.PortSet{ - Definition: flex.ExpandStringSet(tfSet), + if k, ok := tfMap[names.AttrKey].(string); ok && k != "" { + if v, ok := tfMap["port_set"].([]interface{}); ok && len(v) > 0 && v[0] != nil { + if tfMap, ok := v[0].(map[string]interface{}); ok { + if v, ok := tfMap["definition"].(*schema.Set); ok && v.Len() > 0 { + apiObject[k] = awstypes.PortSet{ + Definition: flex.ExpandStringValueSet(v), } - m[key] = ipSet } } } } } - return m + return apiObject } -func expandAddresses(l []interface{}) []*networkfirewall.Address { - if len(l) == 0 || l[0] == nil { +func expandAddresses(tfList []interface{}) []awstypes.Address { + if len(tfList) == 0 || tfList[0] == nil { return nil } - destinations := make([]*networkfirewall.Address, 0, len(l)) - for _, tfMapRaw := range l { + + apiObjects := make([]awstypes.Address, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - destination := &networkfirewall.Address{} + + apiObject := awstypes.Address{} + if v, ok := tfMap["address_definition"].(string); ok && v != "" { - destination.AddressDefinition = aws.String(v) + apiObject.AddressDefinition = aws.String(v) } - destinations = append(destinations, destination) + + apiObjects = append(apiObjects, apiObject) } - return destinations + + return apiObjects } -func expandPortRanges(l []interface{}) []*networkfirewall.PortRange { - if len(l) == 0 || l[0] == nil { +func expandPortRanges(tfList []interface{}) []awstypes.PortRange { + if len(tfList) == 0 || tfList[0] == nil { return nil } - ports := make([]*networkfirewall.PortRange, 0, len(l)) - for _, tfMapRaw := range l { + + apiObjects := make([]awstypes.PortRange, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - port := &networkfirewall.PortRange{} + + apiObject := awstypes.PortRange{} + if v, ok := tfMap["from_port"].(int); ok { - port.FromPort = aws.Int64(int64(v)) + apiObject.FromPort = int32(v) } if v, ok := tfMap["to_port"].(int); ok { - port.ToPort = aws.Int64(int64(v)) + apiObject.ToPort = int32(v) } - ports = append(ports, port) + + apiObjects = append(apiObjects, apiObject) } - return ports + + return apiObjects } -func expandTCPFlags(l []interface{}) []*networkfirewall.TCPFlagField { - if len(l) == 0 || l[0] == nil { +func expandTCPFlags(tfList []interface{}) []awstypes.TCPFlagField { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tcpFlags := make([]*networkfirewall.TCPFlagField, 0, len(l)) - for _, tfMapRaw := range l { + + apiObjects := make([]awstypes.TCPFlagField, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - tcpFlag := &networkfirewall.TCPFlagField{} + + apiObject := awstypes.TCPFlagField{} + if v, ok := tfMap["flags"].(*schema.Set); ok && v.Len() > 0 { - tcpFlag.Flags = flex.ExpandStringSet(v) + apiObject.Flags = flex.ExpandStringyValueSet[awstypes.TCPFlag](v) } if v, ok := tfMap["masks"].(*schema.Set); ok && v.Len() > 0 { - tcpFlag.Masks = flex.ExpandStringSet(v) + apiObject.Masks = flex.ExpandStringyValueSet[awstypes.TCPFlag](v) } - tcpFlags = append(tcpFlags, tcpFlag) + + apiObjects = append(apiObjects, apiObject) } - return tcpFlags + + return apiObjects } -func expandMatchAttributes(l []interface{}) *networkfirewall.MatchAttributes { - if len(l) == 0 || l[0] == nil { +func expandMatchAttributes(tfList []interface{}) *awstypes.MatchAttributes { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - matchAttributes := &networkfirewall.MatchAttributes{} + + apiObject := &awstypes.MatchAttributes{} + if v, ok := tfMap[names.AttrDestination].(*schema.Set); ok && v.Len() > 0 { - matchAttributes.Destinations = expandAddresses(v.List()) + apiObject.Destinations = expandAddresses(v.List()) } if v, ok := tfMap["destination_port"].(*schema.Set); ok && v.Len() > 0 { - matchAttributes.DestinationPorts = expandPortRanges(v.List()) + apiObject.DestinationPorts = expandPortRanges(v.List()) } if v, ok := tfMap["protocols"].(*schema.Set); ok && v.Len() > 0 { - matchAttributes.Protocols = flex.ExpandInt64Set(v) + apiObject.Protocols = flex.ExpandInt32ValueSet(v) } if v, ok := tfMap[names.AttrSource].(*schema.Set); ok && v.Len() > 0 { - matchAttributes.Sources = expandAddresses(v.List()) + apiObject.Sources = expandAddresses(v.List()) } if v, ok := tfMap["source_port"].(*schema.Set); ok && v.Len() > 0 { - matchAttributes.SourcePorts = expandPortRanges(v.List()) + apiObject.SourcePorts = expandPortRanges(v.List()) } if v, ok := tfMap["tcp_flag"].(*schema.Set); ok && v.Len() > 0 { - matchAttributes.TCPFlags = expandTCPFlags(v.List()) + apiObject.TCPFlags = expandTCPFlags(v.List()) } - return matchAttributes + return apiObject } -func expandRuleDefinition(l []interface{}) *networkfirewall.RuleDefinition { - if len(l) == 0 || l[0] == nil { +func expandRuleDefinition(tfList []interface{}) *awstypes.RuleDefinition { + if len(tfList) == 0 || tfList[0] == nil { return nil } - tfMap, ok := l[0].(map[string]interface{}) + + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } - rd := &networkfirewall.RuleDefinition{} + + apiObject := &awstypes.RuleDefinition{} + if v, ok := tfMap[names.AttrActions].(*schema.Set); ok && v.Len() > 0 { - rd.Actions = flex.ExpandStringSet(v) + apiObject.Actions = flex.ExpandStringValueSet(v) } if v, ok := tfMap["match_attributes"].([]interface{}); ok && len(v) > 0 && v[0] != nil { - rd.MatchAttributes = expandMatchAttributes(v) + apiObject.MatchAttributes = expandMatchAttributes(v) } - return rd + + return apiObject } -func expandStatelessRules(l []interface{}) []*networkfirewall.StatelessRule { - if len(l) == 0 || l[0] == nil { +func expandStatelessRules(tfList []interface{}) []awstypes.StatelessRule { + if len(tfList) == 0 || tfList[0] == nil { return nil } - statelessRules := make([]*networkfirewall.StatelessRule, 0, len(l)) - for _, tfMapRaw := range l { + + apiObjects := make([]awstypes.StatelessRule, 0, len(tfList)) + + for _, tfMapRaw := range tfList { tfMap, ok := tfMapRaw.(map[string]interface{}) if !ok { continue } - statelessRule := &networkfirewall.StatelessRule{} + + apiObject := awstypes.StatelessRule{} + if v, ok := tfMap[names.AttrPriority].(int); ok && v > 0 { - statelessRule.Priority = aws.Int64(int64(v)) + apiObject.Priority = aws.Int32(int32(v)) } if v, ok := tfMap["rule_definition"].([]interface{}); ok && len(v) > 0 && v[0] != nil { - statelessRule.RuleDefinition = expandRuleDefinition(v) + apiObject.RuleDefinition = expandRuleDefinition(v) } - statelessRules = append(statelessRules, statelessRule) + + apiObjects = append(apiObjects, apiObject) } - return statelessRules + return apiObjects } -func expandStatelessRulesAndCustomActions(l []interface{}) *networkfirewall.StatelessRulesAndCustomActions { - if len(l) == 0 || l[0] == nil { +func expandStatelessRulesAndCustomActions(tfList []interface{}) *awstypes.StatelessRulesAndCustomActions { + if len(tfList) == 0 || tfList[0] == nil { return nil } - s := &networkfirewall.StatelessRulesAndCustomActions{} - tfMap, ok := l[0].(map[string]interface{}) + apiObject := &awstypes.StatelessRulesAndCustomActions{} + + tfMap, ok := tfList[0].(map[string]interface{}) if !ok { return nil } + if v, ok := tfMap["custom_action"].(*schema.Set); ok && v.Len() > 0 { - s.CustomActions = expandCustomActions(v.List()) + apiObject.CustomActions = expandCustomActions(v.List()) } if v, ok := tfMap["stateless_rule"].(*schema.Set); ok && v.Len() > 0 { - s.StatelessRules = expandStatelessRules(v.List()) + apiObject.StatelessRules = expandStatelessRules(v.List()) } - return s + return apiObject } -func flattenRuleGroup(r *networkfirewall.RuleGroup) []interface{} { - if r == nil { +func flattenRuleGroup(apiObject *awstypes.RuleGroup) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "reference_sets": flattenReferenceSets(r.ReferenceSets), - "rule_variables": flattenRuleVariables(r.RuleVariables), - "rules_source": flattenRulesSource(r.RulesSource), - "stateful_rule_options": flattenStatefulRulesOptions(r.StatefulRuleOptions), + tfMap := map[string]interface{}{ + "reference_sets": flattenReferenceSets(apiObject.ReferenceSets), + "rule_variables": flattenRuleVariables(apiObject.RuleVariables), + "rules_source": flattenRulesSource(apiObject.RulesSource), + "stateful_rule_options": flattenStatefulRulesOptions(apiObject.StatefulRuleOptions), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenReferenceSets(rv *networkfirewall.ReferenceSets) []interface{} { - if rv == nil { +func flattenReferenceSets(apiObject *awstypes.ReferenceSets) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "ip_set_references": flattenIPSetReferences(rv.IPSetReferences), + + tfMap := map[string]interface{}{ + "ip_set_references": flattenIPSetReferences(apiObject.IPSetReferences), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenIPSetReferences(m map[string]*networkfirewall.IPSetReference) []interface{} { - if m == nil { +func flattenIPSetReferences(apiObject map[string]awstypes.IPSetReference) []interface{} { + if apiObject == nil { return []interface{}{} } - sets := make([]interface{}, 0, len(m)) - for k, v := range m { + + tfList := make([]interface{}, 0, len(apiObject)) + + for k, v := range apiObject { tfMap := map[string]interface{}{ + "ip_set_reference": flattenIPSetReference(&v), names.AttrKey: k, - "ip_set_reference": flattenIPSetReference(v), } - sets = append(sets, tfMap) + + tfList = append(tfList, tfMap) } - return sets + return tfList } -func flattenIPSetReference(i *networkfirewall.IPSetReference) []interface{} { - if i == nil { +func flattenIPSetReference(apiObject *awstypes.IPSetReference) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "reference_arn": aws.StringValue(i.ReferenceArn), + + tfMap := map[string]interface{}{ + "reference_arn": aws.ToString(apiObject.ReferenceArn), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenRuleVariables(rv *networkfirewall.RuleVariables) []interface{} { - if rv == nil { +func flattenRuleVariables(apiObject *awstypes.RuleVariables) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "ip_sets": flattenIPSets(rv.IPSets), - "port_sets": flattenPortSets(rv.PortSets), + + tfMap := map[string]interface{}{ + "ip_sets": flattenIPSets(apiObject.IPSets), + "port_sets": flattenPortSets(apiObject.PortSets), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenPortSets(m map[string]*networkfirewall.PortSet) []interface{} { - if m == nil { +func flattenPortSets(apiObject map[string]awstypes.PortSet) []interface{} { + if apiObject == nil { return []interface{}{} } - sets := make([]interface{}, 0, len(m)) - for k, v := range m { + + tfList := make([]interface{}, 0, len(apiObject)) + + for k, v := range apiObject { tfMap := map[string]interface{}{ names.AttrKey: k, - "port_set": flattenPortSet(v), + "port_set": flattenPortSet(&v), } - sets = append(sets, tfMap) + + tfList = append(tfList, tfMap) } - return sets + return tfList } -func flattenPortSet(p *networkfirewall.PortSet) []interface{} { - if p == nil { +func flattenPortSet(apiObject *awstypes.PortSet) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "definition": flex.FlattenStringSet(p.Definition), + + tfMap := map[string]interface{}{ + "definition": apiObject.Definition, } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenRulesSource(rs *networkfirewall.RulesSource) []interface{} { - if rs == nil { +func flattenRulesSource(apiObject *awstypes.RulesSource) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "rules_source_list": flattenRulesSourceList(rs.RulesSourceList), - "rules_string": aws.StringValue(rs.RulesString), - "stateful_rule": flattenStatefulRules(rs.StatefulRules), - "stateless_rules_and_custom_actions": flattenStatelessRulesAndCustomActions(rs.StatelessRulesAndCustomActions), + tfMap := map[string]interface{}{ + "rules_source_list": flattenRulesSourceList(apiObject.RulesSourceList), + "rules_string": aws.ToString(apiObject.RulesString), + "stateful_rule": flattenStatefulRules(apiObject.StatefulRules), + "stateless_rules_and_custom_actions": flattenStatelessRulesAndCustomActions(apiObject.StatelessRulesAndCustomActions), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenRulesSourceList(r *networkfirewall.RulesSourceList) []interface{} { - if r == nil { +func flattenRulesSourceList(apiObject *awstypes.RulesSourceList) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "generated_rules_type": aws.StringValue(r.GeneratedRulesType), - "target_types": flex.FlattenStringSet(r.TargetTypes), - "targets": flex.FlattenStringSet(r.Targets), + tfMap := map[string]interface{}{ + "generated_rules_type": apiObject.GeneratedRulesType, + "target_types": apiObject.TargetTypes, + "targets": apiObject.Targets, } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenStatefulRules(sr []*networkfirewall.StatefulRule) []interface{} { - if sr == nil { +func flattenStatefulRules(apiObjects []awstypes.StatefulRule) []interface{} { + if apiObjects == nil { return []interface{}{} } - rules := make([]interface{}, 0, len(sr)) - for _, s := range sr { + + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { m := map[string]interface{}{ - names.AttrAction: aws.StringValue(s.Action), - names.AttrHeader: flattenHeader(s.Header), - "rule_option": flattenRuleOptions(s.RuleOptions), + names.AttrAction: apiObject.Action, + names.AttrHeader: flattenHeader(apiObject.Header), + "rule_option": flattenRuleOptions(apiObject.RuleOptions), } - rules = append(rules, m) + + tfList = append(tfList, m) } - return rules + + return tfList } -func flattenHeader(h *networkfirewall.Header) []interface{} { - if h == nil { +func flattenHeader(apiObject *awstypes.Header) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - names.AttrDestination: aws.StringValue(h.Destination), - "destination_port": aws.StringValue(h.DestinationPort), - "direction": aws.StringValue(h.Direction), - names.AttrProtocol: aws.StringValue(h.Protocol), - names.AttrSource: aws.StringValue(h.Source), - "source_port": aws.StringValue(h.SourcePort), + tfMap := map[string]interface{}{ + names.AttrDestination: aws.ToString(apiObject.Destination), + "destination_port": aws.ToString(apiObject.DestinationPort), + "direction": apiObject.Direction, + names.AttrProtocol: apiObject.Protocol, + names.AttrSource: aws.ToString(apiObject.Source), + "source_port": aws.ToString(apiObject.SourcePort), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenRuleOptions(o []*networkfirewall.RuleOption) []interface{} { - if o == nil { +func flattenRuleOptions(apiObjects []awstypes.RuleOption) []interface{} { + if apiObjects == nil { return []interface{}{} } - options := make([]interface{}, 0, len(o)) - for _, option := range o { - m := map[string]interface{}{ - "keyword": aws.StringValue(option.Keyword), - "settings": aws.StringValueSlice(option.Settings), + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + "keyword": aws.ToString(apiObject.Keyword), + "settings": apiObject.Settings, } - options = append(options, m) + + tfList = append(tfList, tfMap) } - return options + return tfList } -func flattenStatelessRulesAndCustomActions(sr *networkfirewall.StatelessRulesAndCustomActions) []interface{} { - if sr == nil { +func flattenStatelessRulesAndCustomActions(apiObject *awstypes.StatelessRulesAndCustomActions) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "custom_action": flattenCustomActions(sr.CustomActions), - "stateless_rule": flattenStatelessRules(sr.StatelessRules), + tfMap := map[string]interface{}{ + "custom_action": flattenCustomActions(apiObject.CustomActions), + "stateless_rule": flattenStatelessRules(apiObject.StatelessRules), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenStatelessRules(sr []*networkfirewall.StatelessRule) []interface{} { - if sr == nil { +func flattenStatelessRules(apiObjects []awstypes.StatelessRule) []interface{} { + if apiObjects == nil { return []interface{}{} } - rules := make([]interface{}, 0, len(sr)) - for _, s := range sr { - rule := map[string]interface{}{ - names.AttrPriority: int(aws.Int64Value(s.Priority)), - "rule_definition": flattenRuleDefinition(s.RuleDefinition), + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + names.AttrPriority: aws.ToInt32(apiObject.Priority), + "rule_definition": flattenRuleDefinition(apiObject.RuleDefinition), } - rules = append(rules, rule) + + tfList = append(tfList, tfMap) } - return rules + return tfList } -func flattenRuleDefinition(r *networkfirewall.RuleDefinition) []interface{} { - if r == nil { +func flattenRuleDefinition(apiObject *awstypes.RuleDefinition) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - names.AttrActions: flex.FlattenStringSet(r.Actions), - "match_attributes": flattenMatchAttributes(r.MatchAttributes), + tfMap := map[string]interface{}{ + names.AttrActions: apiObject.Actions, + "match_attributes": flattenMatchAttributes(apiObject.MatchAttributes), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenMatchAttributes(ma *networkfirewall.MatchAttributes) []interface{} { - if ma == nil { +func flattenMatchAttributes(apiObject *awstypes.MatchAttributes) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - names.AttrDestination: flattenAddresses(ma.Destinations), - "destination_port": flattenPortRanges(ma.DestinationPorts), - "protocols": flex.FlattenInt64Set(ma.Protocols), - names.AttrSource: flattenAddresses(ma.Sources), - "source_port": flattenPortRanges(ma.SourcePorts), - "tcp_flag": flattenTCPFlags(ma.TCPFlags), + tfMap := map[string]interface{}{ + names.AttrDestination: flattenAddresses(apiObject.Destinations), + "destination_port": flattenPortRanges(apiObject.DestinationPorts), + "protocols": apiObject.Protocols, + names.AttrSource: flattenAddresses(apiObject.Sources), + "source_port": flattenPortRanges(apiObject.SourcePorts), + "tcp_flag": flattenTCPFlags(apiObject.TCPFlags), } - return []interface{}{m} + return []interface{}{tfMap} } -func flattenAddresses(d []*networkfirewall.Address) []interface{} { - if d == nil { +func flattenAddresses(apiObjects []awstypes.Address) []interface{} { + if apiObjects == nil { return []interface{}{} } - destinations := make([]interface{}, 0, len(d)) - for _, addr := range d { - m := map[string]interface{}{ - "address_definition": aws.StringValue(addr.AddressDefinition), + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + "address_definition": aws.ToString(apiObject.AddressDefinition), } - destinations = append(destinations, m) + + tfList = append(tfList, tfMap) } - return destinations + return tfList } -func flattenPortRanges(pr []*networkfirewall.PortRange) []interface{} { - if pr == nil { +func flattenPortRanges(apiObjects []awstypes.PortRange) []interface{} { + if apiObjects == nil { return []interface{}{} } - portRanges := make([]interface{}, 0, len(pr)) - for _, r := range pr { - m := map[string]interface{}{ - "from_port": int(aws.Int64Value(r.FromPort)), - "to_port": int(aws.Int64Value(r.ToPort)), + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { + tfMap := map[string]interface{}{ + "from_port": apiObject.FromPort, + "to_port": apiObject.ToPort, } - portRanges = append(portRanges, m) + + tfList = append(tfList, tfMap) } - return portRanges + return tfList } -func flattenTCPFlags(t []*networkfirewall.TCPFlagField) []interface{} { - if t == nil { +func flattenTCPFlags(apiObjects []awstypes.TCPFlagField) []interface{} { + if apiObjects == nil { return []interface{}{} } - flagFields := make([]interface{}, 0, len(t)) - for _, v := range t { + + tfList := make([]interface{}, 0, len(apiObjects)) + + for _, apiObject := range apiObjects { m := map[string]interface{}{ - "flags": flex.FlattenStringSet(v.Flags), - "masks": flex.FlattenStringSet(v.Masks), + "flags": apiObject.Flags, + "masks": apiObject.Masks, } - flagFields = append(flagFields, m) + + tfList = append(tfList, m) } - return flagFields + return tfList } -func flattenStatefulRulesOptions(sro *networkfirewall.StatefulRuleOptions) []interface{} { - if sro == nil { +func flattenStatefulRulesOptions(apiObject *awstypes.StatefulRuleOptions) []interface{} { + if apiObject == nil { return []interface{}{} } - m := map[string]interface{}{ - "rule_order": aws.StringValue(sro.RuleOrder), + tfMap := map[string]interface{}{ + "rule_order": apiObject.RuleOrder, } - return []interface{}{m} + return []interface{}{tfMap} } diff --git a/internal/service/networkfirewall/rule_group_test.go b/internal/service/networkfirewall/rule_group_test.go index 1ccf7ffa11b..f4636ff8e46 100644 --- a/internal/service/networkfirewall/rule_group_test.go +++ b/internal/service/networkfirewall/rule_group_test.go @@ -8,8 +8,9 @@ import ( "fmt" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" + awstypes "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -39,14 +40,14 @@ func TestAccNetworkFirewallRuleGroup_Basic_rulesSourceList(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateful-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateful), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateful)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.reference_sets.#", acctest.Ct0), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.generated_rules_type", networkfirewall.GeneratedRulesTypeAllowlist), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.generated_rules_type", string(awstypes.GeneratedRulesTypeAllowlist)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.#", acctest.Ct1), - resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.*", networkfirewall.TargetTypeHttpHost), + resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.*", string(awstypes.TargetTypeHttpHost)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.targets.#", acctest.Ct1), resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.targets.*", "test.example.com"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rule_variables.#", acctest.Ct0), @@ -82,7 +83,7 @@ func TestAccNetworkFirewallRuleGroup_Basic_referenceSets(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateful-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateful), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateful)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.reference_sets.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.reference_sets.0.ip_set_references.#", acctest.Ct3), @@ -119,7 +120,7 @@ func TestAccNetworkFirewallRuleGroup_Basic_updateReferenceSets(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateful-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateful), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateful)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.reference_sets.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.reference_sets.0.ip_set_references.#", acctest.Ct3), @@ -140,7 +141,7 @@ func TestAccNetworkFirewallRuleGroup_Basic_updateReferenceSets(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateful-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateful), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateful)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.reference_sets.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.reference_sets.0.ip_set_references.#", acctest.Ct3), @@ -172,16 +173,16 @@ func TestAccNetworkFirewallRuleGroup_Basic_statefulRule(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateful-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateful), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateful)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionPass)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "124.1.1.24/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "53"), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", string(awstypes.StatefulRuleProtocolTcp)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "1.2.3.4/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "53"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", acctest.Ct1), @@ -222,7 +223,7 @@ func TestAccNetworkFirewallRuleGroup_Basic_statelessRule(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateless-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateless), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateless)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateless_rules_and_custom_actions.#", acctest.Ct1), @@ -268,7 +269,7 @@ alert http any any -> any any (http_response_line; content:"403 Forbidden"; sid: acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateful-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateful), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateful)), resource.TestCheckResourceAttr(resourceName, "rules", rules), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.#", acctest.Ct1), @@ -305,7 +306,7 @@ func TestAccNetworkFirewallRuleGroup_statefulRuleOptions(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.0.rule_order", networkfirewall.RuleOrderStrictOrder), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.0.rule_order", string(awstypes.RuleOrderStrictOrder)), ), }, { @@ -335,7 +336,7 @@ func TestAccNetworkFirewallRuleGroup_updateStatefulRuleOptions(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.0.rule_order", networkfirewall.RuleOrderStrictOrder), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.0.rule_order", string(awstypes.RuleOrderStrictOrder)), ), }, { @@ -344,7 +345,7 @@ func TestAccNetworkFirewallRuleGroup_updateStatefulRuleOptions(t *testing.T) { testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup2), testAccCheckRuleGroupRecreated(&ruleGroup1, &ruleGroup2), resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.0.rule_order", networkfirewall.RuleOrderDefaultActionOrder), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.stateful_rule_options.0.rule_order", string(awstypes.RuleOrderDefaultActionOrder)), ), }, { @@ -383,7 +384,7 @@ func TestAccNetworkFirewallRuleGroup_statelessRuleWithCustomAction(t *testing.T) acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateless-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateless), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateless)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateless_rules_and_custom_actions.#", acctest.Ct1), @@ -482,14 +483,14 @@ func TestAccNetworkFirewallRuleGroup_updateRulesSourceList(t *testing.T) { acctest.CheckResourceAttrRegionalARN(resourceName, names.AttrARN, "network-firewall", fmt.Sprintf("stateful-rulegroup/%s", rName)), resource.TestCheckResourceAttr(resourceName, "capacity", "100"), resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, names.AttrType, networkfirewall.RuleGroupTypeStateful), + resource.TestCheckResourceAttr(resourceName, names.AttrType, string(awstypes.RuleGroupTypeStateful)), resource.TestCheckResourceAttr(resourceName, "rule_group.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.generated_rules_type", networkfirewall.GeneratedRulesTypeDenylist), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.generated_rules_type", string(awstypes.GeneratedRulesTypeDenylist)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.#", acctest.Ct2), - resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.*", networkfirewall.TargetTypeHttpHost), - resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.*", networkfirewall.TargetTypeTlsSni), + resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.*", string(awstypes.TargetTypeHttpHost)), + resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.target_types.*", string(awstypes.TargetTypeTlsSni)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.targets.#", acctest.Ct2), resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.targets.*", "test.example.com"), resource.TestCheckTypeSetElemAttr(resourceName, "rule_group.0.rules_source.0.rules_source_list.0.targets.*", "test2.example.com"), @@ -608,12 +609,12 @@ func TestAccNetworkFirewallRuleGroup_updateStatefulRule(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionDrop), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionDrop)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "1.2.3.4/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "1001"), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionForward), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolIp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", string(awstypes.StatefulRuleDirectionForward)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", string(awstypes.StatefulRuleProtocolAny)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "124.1.1.24/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "1001"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", acctest.Ct2), @@ -665,23 +666,23 @@ func TestAccNetworkFirewallRuleGroup_updateMultipleStatefulRules(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct2), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionPass)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "124.1.1.24/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "53"), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", string(awstypes.StatefulRuleProtocolTcp)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "1.2.3.4/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "53"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.action", networkfirewall.StatefulActionAlert), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.action", string(awstypes.StatefulActionAlert)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.destination", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.destination_port", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.direction", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.protocol", networkfirewall.StatefulRuleProtocolIp), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.source", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.source_port", networkfirewall.StatefulRuleDirectionAny), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.destination", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.destination_port", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.direction", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.protocol", string(awstypes.StatefulRuleProtocolAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.source", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.header.0.source_port", string(awstypes.StatefulRuleDirectionAny)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.1.rule_option.#", acctest.Ct1), ), }, @@ -695,12 +696,12 @@ func TestAccNetworkFirewallRuleGroup_updateMultipleStatefulRules(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionDrop), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionDrop)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "1.2.3.4/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "1001"), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionForward), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolIp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", string(awstypes.StatefulRuleDirectionForward)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", string(awstypes.StatefulRuleProtocolAny)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "124.1.1.24/32"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "1001"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", acctest.Ct2), @@ -731,11 +732,11 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_action(t *testing.T) { CheckDestroy: testAccCheckRuleGroupDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccRuleGroupConfig_statefulAction(rName, networkfirewall.StatefulActionAlert), + Config: testAccRuleGroupConfig_statefulAction(rName, string(awstypes.StatefulActionAlert)), Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionAlert), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionAlert)), ), }, { @@ -744,11 +745,11 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_action(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRuleGroupConfig_statefulAction(rName, networkfirewall.StatefulActionPass), + Config: testAccRuleGroupConfig_statefulAction(rName, string(awstypes.StatefulActionPass)), Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionPass)), ), }, { @@ -757,11 +758,11 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_action(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRuleGroupConfig_statefulAction(rName, networkfirewall.StatefulActionDrop), + Config: testAccRuleGroupConfig_statefulAction(rName, string(awstypes.StatefulActionDrop)), Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionDrop), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionDrop)), ), }, { @@ -770,11 +771,11 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_action(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccRuleGroupConfig_statefulAction(rName, networkfirewall.StatefulActionReject), + Config: testAccRuleGroupConfig_statefulAction(rName, string(awstypes.StatefulActionReject)), Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionReject), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionReject)), ), }, { @@ -804,12 +805,12 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_header(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionPass)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "ANY"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "1990"), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", string(awstypes.StatefulRuleProtocolTcp)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "ANY"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "1994"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", acctest.Ct1), @@ -825,12 +826,12 @@ func TestAccNetworkFirewallRuleGroup_StatefulRule_header(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckRuleGroupExists(ctx, resourceName, &ruleGroup), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.#", acctest.Ct1), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", networkfirewall.StatefulActionPass), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.action", string(awstypes.StatefulActionPass)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.#", acctest.Ct1), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination", "ANY"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.destination_port", "ANY"), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", networkfirewall.StatefulRuleDirectionAny), - resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", networkfirewall.StatefulRuleProtocolTcp), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.direction", string(awstypes.StatefulRuleDirectionAny)), + resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.protocol", string(awstypes.StatefulRuleProtocolTcp)), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source", "ANY"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.header.0.source_port", "ANY"), resource.TestCheckResourceAttr(resourceName, "rule_group.0.rules_source.0.stateful_rule.0.rule_option.#", acctest.Ct1), @@ -1024,7 +1025,7 @@ func testAccCheckRuleGroupDestroy(ctx context.Context) resource.TestCheckFunc { continue } - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) _, err := tfnetworkfirewall.FindRuleGroupByARN(ctx, conn, rs.Primary.ID) @@ -1050,11 +1051,7 @@ func testAccCheckRuleGroupExists(ctx context.Context, n string, v *networkfirewa return fmt.Errorf("Not found: %s", n) } - if rs.Primary.ID == "" { - return fmt.Errorf("No NetworkFirewall Rule Group ID is set") - } - - conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).NetworkFirewallClient(ctx) output, err := tfnetworkfirewall.FindRuleGroupByARN(ctx, conn, rs.Primary.ID) @@ -1070,7 +1067,7 @@ func testAccCheckRuleGroupExists(ctx context.Context, n string, v *networkfirewa func testAccCheckRuleGroupNotRecreated(i, j *networkfirewall.DescribeRuleGroupOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - if before, after := aws.StringValue(i.RuleGroupResponse.RuleGroupId), aws.StringValue(j.RuleGroupResponse.RuleGroupId); before != after { + if before, after := aws.ToString(i.RuleGroupResponse.RuleGroupId), aws.ToString(j.RuleGroupResponse.RuleGroupId); before != after { return fmt.Errorf("NetworkFirewall Rule Group was recreated. got: %s, expected: %s", after, before) } return nil @@ -1079,7 +1076,7 @@ func testAccCheckRuleGroupNotRecreated(i, j *networkfirewall.DescribeRuleGroupOu func testAccCheckRuleGroupRecreated(i, j *networkfirewall.DescribeRuleGroupOutput) resource.TestCheckFunc { return func(s *terraform.State) error { - if before, after := aws.StringValue(i.RuleGroupResponse.RuleGroupId), aws.StringValue(j.RuleGroupResponse.RuleGroupId); before == after { + if before, after := aws.ToString(i.RuleGroupResponse.RuleGroupId), aws.ToString(j.RuleGroupResponse.RuleGroupId); before == after { return fmt.Errorf("NetworkFirewall Rule Group (%s) was not recreated", before) } return nil diff --git a/internal/service/networkfirewall/service_package_gen.go b/internal/service/networkfirewall/service_package_gen.go index 3ced3bcdff1..bf2747a106d 100644 --- a/internal/service/networkfirewall/service_package_gen.go +++ b/internal/service/networkfirewall/service_package_gen.go @@ -82,7 +82,7 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka Name: "Resource Policy", }, { - Factory: ResourceRuleGroup, + Factory: resourceRuleGroup, TypeName: "aws_networkfirewall_rule_group", Name: "Rule Group", Tags: &types.ServicePackageResourceTags{ From 468e5cc4ee8f5a7e7c2814a796a646e300e1e458 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 13:44:29 -0400 Subject: [PATCH 62/68] networkfirewall: Migrate sweepers to AWS SDK for Go v2. --- internal/service/networkfirewall/sweep.go | 130 ++++++++++------------ 1 file changed, 59 insertions(+), 71 deletions(-) diff --git a/internal/service/networkfirewall/sweep.go b/internal/service/networkfirewall/sweep.go index 5f06cb358ab..1d4f7859bbd 100644 --- a/internal/service/networkfirewall/sweep.go +++ b/internal/service/networkfirewall/sweep.go @@ -7,11 +7,11 @@ import ( "fmt" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/networkfirewall" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/networkfirewall" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-provider-aws/internal/sweep" - "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv1" + "github.com/hashicorp/terraform-provider-aws/internal/sweep/awsv2" ) func RegisterSweepers() { @@ -51,33 +51,30 @@ func sweepFirewallPolicies(region string) error { if err != nil { return fmt.Errorf("error getting client: %w", err) } - conn := client.NetworkFirewallConn(ctx) + conn := client.NetworkFirewallClient(ctx) input := &networkfirewall.ListFirewallPoliciesInput{} sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListFirewallPoliciesPagesWithContext(ctx, input, func(page *networkfirewall.ListFirewallPoliciesOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := networkfirewall.NewListFirewallPoliciesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping NetworkFirewall Firewall Policy sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing NetworkFirewall Firewall Policies (%s): %w", region, err) } for _, v := range page.FirewallPolicies { - r := ResourceFirewallPolicy() + r := resourceFirewallPolicy() d := r.Data(nil) - d.SetId(aws.StringValue(v.Arn)) + d.SetId(aws.ToString(v.Arn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping NetworkFirewall Firewall Policy sweep for %s: %s", region, err) - return nil - } - - if err != nil { - return fmt.Errorf("error listing NetworkFirewall Firewall Policies (%s): %w", region, err) } err = sweep.SweepOrchestrator(ctx, sweepResources) @@ -95,33 +92,30 @@ func sweepFirewalls(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.NetworkFirewallConn(ctx) + conn := client.NetworkFirewallClient(ctx) input := &networkfirewall.ListFirewallsInput{} sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListFirewallsPagesWithContext(ctx, input, func(page *networkfirewall.ListFirewallsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := networkfirewall.NewListFirewallsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping NetworkFirewall Firewall sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing NetworkFirewall Firewalls (%s): %w", region, err) } for _, v := range page.Firewalls { - r := ResourceFirewall() + r := resourceFirewall() d := r.Data(nil) - d.SetId(aws.StringValue(v.FirewallArn)) + d.SetId(aws.ToString(v.FirewallArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping NetworkFirewall Firewall sweep for %s: %s", region, err) - return nil - } - - if err != nil { - return fmt.Errorf("error listing NetworkFirewall Firewalls (%s): %w", region, err) } err = sweep.SweepOrchestrator(ctx, sweepResources) @@ -139,33 +133,30 @@ func sweepLoggingConfigurations(region string) error { if err != nil { return fmt.Errorf("error getting client: %s", err) } - conn := client.NetworkFirewallConn(ctx) + conn := client.NetworkFirewallClient(ctx) input := &networkfirewall.ListFirewallsInput{} sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListFirewallsPagesWithContext(ctx, input, func(page *networkfirewall.ListFirewallsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := networkfirewall.NewListFirewallsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping NetworkFirewall Logging Configuration sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing NetworkFirewall Firewalls (%s): %w", region, err) } for _, v := range page.Firewalls { - r := ResourceLoggingConfiguration() + r := resourceLoggingConfiguration() d := r.Data(nil) - d.SetId(aws.StringValue(v.FirewallArn)) + d.SetId(aws.ToString(v.FirewallArn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping NetworkFirewall Logging Configuration sweep for %s: %s", region, err) - return nil - } - - if err != nil { - return fmt.Errorf("error listing NetworkFirewall Firewalls (%s): %w", region, err) } err = sweep.SweepOrchestrator(ctx, sweepResources) @@ -183,33 +174,30 @@ func sweepRuleGroups(region string) error { if err != nil { return fmt.Errorf("error getting client: %w", err) } - conn := client.NetworkFirewallConn(ctx) + conn := client.NetworkFirewallClient(ctx) input := &networkfirewall.ListRuleGroupsInput{} sweepResources := make([]sweep.Sweepable, 0) - err = conn.ListRuleGroupsPagesWithContext(ctx, input, func(page *networkfirewall.ListRuleGroupsOutput, lastPage bool) bool { - if page == nil { - return !lastPage + pages := networkfirewall.NewListRuleGroupsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping NetworkFirewall Rule Group sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing NetworkFirewall Rule Groups (%s): %w", region, err) } for _, v := range page.RuleGroups { - r := ResourceRuleGroup() + r := resourceRuleGroup() d := r.Data(nil) - d.SetId(aws.StringValue(v.Arn)) + d.SetId(aws.ToString(v.Arn)) sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) } - - return !lastPage - }) - - if awsv1.SkipSweepError(err) { - log.Printf("[WARN] Skipping NetworkFirewall Rule Group sweep for %s: %s", region, err) - return nil - } - - if err != nil { - return fmt.Errorf("error listing NetworkFirewall Rule Groups (%s): %w", region, err) } err = sweep.SweepOrchestrator(ctx, sweepResources) From 4b4d524e65e025d76a55569da289be3de120dd79 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 13:46:13 -0400 Subject: [PATCH 63/68] Fix smegrep 'ci.literal-source-string-constant'. --- .../service/networkfirewall/tls_inspection_configuration.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/networkfirewall/tls_inspection_configuration.go b/internal/service/networkfirewall/tls_inspection_configuration.go index a83324f9a7b..d4444801b56 100644 --- a/internal/service/networkfirewall/tls_inspection_configuration.go +++ b/internal/service/networkfirewall/tls_inspection_configuration.go @@ -242,7 +242,7 @@ func (r *tlsInspectionConfigurationResource) Schema(ctx context.Context, request }, }, }, - "source": schema.ListNestedBlock{ + names.AttrSource: schema.ListNestedBlock{ CustomType: fwtypes.NewListNestedObjectTypeOf[addressModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ From f20acb293bc514066cf5b7501b0d6b4b68bb17f5 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 13:50:46 -0400 Subject: [PATCH 64/68] Fix golangci-lint 'ineffassign'. --- internal/service/networkfirewall/firewall.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/networkfirewall/firewall.go b/internal/service/networkfirewall/firewall.go index 47c26c7d172..651e8e51001 100644 --- a/internal/service/networkfirewall/firewall.go +++ b/internal/service/networkfirewall/firewall.go @@ -386,13 +386,13 @@ func resourceFirewallUpdate(ctx context.Context, d *schema.ResourceData, meta in _, err := conn.DisassociateSubnets(ctx, input) if err == nil { - output, err := waitFirewallUpdated(ctx, conn, d.Timeout(schema.TimeoutUpdate), d.Id()) + /*output*/ _, err := waitFirewallUpdated(ctx, conn, d.Timeout(schema.TimeoutUpdate), d.Id()) if err != nil { return sdkdiag.AppendErrorf(diags, "waiting for NetworkFirewall Firewall (%s) update: %s", d.Id(), err) } - updateToken = aws.ToString(output.UpdateToken) + // updateToken = aws.ToString(output.UpdateToken) } else if !errs.IsAErrorMessageContains[*awstypes.InvalidRequestException](err, "inaccessible") { return sdkdiag.AppendErrorf(diags, "disassociating NetworkFirewall Firewall (%s) subnets: %s", d.Id(), err) } From dfa6a8edd8301014520e7f85c8de2b91fe789655 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 13:56:47 -0400 Subject: [PATCH 65/68] d/aws_networkfirewall_firewall: 'tags' is Computed. --- internal/service/networkfirewall/firewall_data_source.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/networkfirewall/firewall_data_source.go b/internal/service/networkfirewall/firewall_data_source.go index ef2ee4f8c30..580f53449ba 100644 --- a/internal/service/networkfirewall/firewall_data_source.go +++ b/internal/service/networkfirewall/firewall_data_source.go @@ -173,7 +173,7 @@ func dataSourceFirewall() *schema.Resource { }, }, }, - names.AttrTags: tftags.TagsSchema(), + names.AttrTags: tftags.TagsSchemaComputed(), "update_token": { Type: schema.TypeString, Computed: true, From 30b897332ab6004d0f251080d26e8a53bc256bd3 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 14:05:09 -0400 Subject: [PATCH 66/68] r/aws_networkfirewall_firewall_policy: Fix acceptance tests. --- .../networkfirewall/firewall_policy_test.go | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/internal/service/networkfirewall/firewall_policy_test.go b/internal/service/networkfirewall/firewall_policy_test.go index 21e4ff97e67..0b84c4dc2f7 100644 --- a/internal/service/networkfirewall/firewall_policy_test.go +++ b/internal/service/networkfirewall/firewall_policy_test.go @@ -355,9 +355,10 @@ func TestAccNetworkFirewallFirewallPolicy_statefulRuleGroupReference(t *testing. ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"firewall_policy.0.stateful_rule_group_reference.0.priority"}, }, }, }) @@ -382,9 +383,10 @@ func TestAccNetworkFirewallFirewallPolicy_statefulRuleGroupReferenceManaged(t *t ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"firewall_policy.0.stateful_rule_group_reference.0.priority"}, }, }, }) @@ -467,9 +469,10 @@ func TestAccNetworkFirewallFirewallPolicy_multipleStatefulRuleGroupReferences(t ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"firewall_policy.0.stateful_rule_group_reference.0.priority"}, }, }, }) @@ -528,9 +531,10 @@ func TestAccNetworkFirewallFirewallPolicy_statefulRuleGroupOverrideActionReferen ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"firewall_policy.0.stateful_rule_group_reference.0.priority"}, }, }, }) @@ -916,9 +920,10 @@ func TestAccNetworkFirewallFirewallPolicy_statefulRuleGroupReferenceAndCustomAct ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"firewall_policy.0.stateful_rule_group_reference.0.priority"}, }, }, }) From 4053ac7293c200d57bbfbf8335425517ca79879a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 14:24:07 -0400 Subject: [PATCH 67/68] r/aws_ec2_managed_prefix_list: Add sweeper. --- internal/service/ec2/sweep.go | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/internal/service/ec2/sweep.go b/internal/service/ec2/sweep.go index 760bfb77757..56172128e7e 100644 --- a/internal/service/ec2/sweep.go +++ b/internal/service/ec2/sweep.go @@ -174,6 +174,16 @@ func RegisterSweepers() { }, }) + resource.AddTestSweepers("aws_ec2_managed_prefix_list", &resource.Sweeper{ + Name: "aws_ec2_managed_prefix_list", + F: sweepManagedPrefixLists, + Dependencies: []string{ + "aws_route_table", + "aws_security_group", + "aws_networkfirewall_rule_group", + }, + }) + resource.AddTestSweepers("aws_ec2_network_insights_path", &resource.Sweeper{ Name: "aws_ec2_network_insights_path", F: sweepNetworkInsightsPaths, @@ -1355,6 +1365,51 @@ func sweepNetworkInterfaces(region string) error { return nil } +func sweepManagedPrefixLists(region string) error { + ctx := sweep.Context(region) + client, err := sweep.SharedRegionalSweepClient(ctx, region) + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + conn := client.EC2Client(ctx) + sweepResources := make([]sweep.Sweepable, 0) + + pages := ec2.NewDescribeManagedPrefixListsPaginator(conn, &ec2.DescribeManagedPrefixListsInput{}) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if awsv2.SkipSweepError(err) { + log.Printf("[WARN] Skipping EC2 Managed Prefix List sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error listing EC2 Managed Prefix Lists (%s): %w", region, err) + } + + for _, v := range page.PrefixLists { + if aws.ToString(v.OwnerId) == "AWS" { + log.Printf("[DEBUG] Skipping AWS-managed prefix list: %s", aws.ToString(v.PrefixListName)) + continue + } + + r := ResourceManagedPrefixList() + d := r.Data(nil) + d.SetId(aws.ToString(v.PrefixListId)) + + sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client)) + } + } + + err = sweep.SweepOrchestrator(ctx, sweepResources) + + if err != nil { + return fmt.Errorf("error sweeping EC2 Managed Prefix Lists (%s): %w", region, err) + } + + return nil +} + func sweepNetworkInsightsPaths(region string) error { ctx := sweep.Context(region) client, err := sweep.SharedRegionalSweepClient(ctx, region) From e4cb7649936a111f7a0f3824145f35cafab132f0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2024 17:11:32 -0400 Subject: [PATCH 68/68] r/aws_networkfirewall_rule_group: Correct NotFoundError. --- internal/service/networkfirewall/rule_group.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/service/networkfirewall/rule_group.go b/internal/service/networkfirewall/rule_group.go index 5b775b65e4f..44116d96867 100644 --- a/internal/service/networkfirewall/rule_group.go +++ b/internal/service/networkfirewall/rule_group.go @@ -508,6 +508,10 @@ func resourceRuleGroupRead(ctx context.Context, d *schema.ResourceData, meta int output, err := findRuleGroupByARN(ctx, conn, d.Id()) + if err == nil && output.RuleGroup == nil { + err = tfresource.NewEmptyResultError(d.Id()) + } + if !d.IsNewResource() && tfresource.NotFound(err) { log.Printf("[WARN] NetworkFirewall Rule Group (%s) not found, removing from state", d.Id()) d.SetId("") @@ -633,7 +637,7 @@ func findRuleGroupByARN(ctx context.Context, conn *networkfirewall.Client, arn s return nil, err } - if output == nil || output.RuleGroup == nil || output.RuleGroupResponse == nil { + if output == nil || output.RuleGroupResponse == nil { return nil, tfresource.NewEmptyResultError(input) }