hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.74k stars 9.1k forks source link

[Bug]: arnType custom type implementation prevents validation to work properly #39227

Open marcinbelczewski opened 1 week ago

marcinbelczewski commented 1 week ago

Terraform Core Version

1.9.5

AWS Provider Version

5.66.0

Affected Resource(s)

Any resource which currently uses ARNType custom type implementation and there are many

Expected Behavior

When invalid ARN is passed to attribute of type ARNType, some kind of validation error should appear during terraform plan

Actual Behavior

An error suggesting a bug in the provider is displayed:

Error: Provider produced invalid plan
│
│ Provider "registry.terraform.io/hashicorp/aws" planned an invalid value for <RESOURCE_WITH_ARN_ATTRIBUTE>: planned value cty.UnknownVal(cty.String) does not match
│ config value cty.StringVal("<SOME_INVALID_ARN>").
│
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.

Relevant Error/Panic Output Snippet

No response

Terraform Configuration Files

Problem can be reproduced using any resource which has ARNType attributes. For example:

resource "aws_bedrockagent_agent" "test" {
  agent_name              = "test"
  agent_resource_role_arn = "INVALID-ARN"
  foundation_model        = "test"
}

will cause the problem.

Also, the minimal resource implementation reproduces the problem:

// @FrameworkResource("aws_test_arn", name="TestArn")
func newResourceTestArn(_ context.Context) (resource.ResourceWithConfigure, error) {
    r := &resourceTestArn{}
    return r, nil
}

type resourceTestArn struct {
    framework.ResourceWithConfigure
}

func (r *resourceTestArn) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
    resp.TypeName = "aws_test_arn"
}

func (r *resourceTestArn) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
    resp.Schema = schema.Schema{
        Attributes: map[string]schema.Attribute{
            "arn": schema.StringAttribute{
                CustomType: fwtypes.ARNType,
                Required:   true,
            },
        },
    }
}

func (r *resourceTestArn) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
}
func (r *resourceTestArn) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
}
func (r *resourceTestArn) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
}
func (r *resourceTestArn) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

this resource will demonstrate the error with the following config:

resource "aws_test_arn" "test" {
  arn = "INVALID-ARN"
}

Steps to Reproduce

Use any of the snippets provided above and just run terraform plan

Debug Output

plan.log This is the plan for aws_bedrockagent_agent snippet suggested above.

Panic Output

No response

Important Factoids

The cause of the issue seems to be implementation of the ARNType

This method:

func (t arnType) ValueFromString(_ context.Context, in types.String) (basetypes.StringValuable, diag.Diagnostics) {
    var diags diag.Diagnostics

    if in.IsNull() {
        return ARNNull(), diags
    }
    if in.IsUnknown() {
        return ARNUnknown(), diags
    }

    valueString := in.ValueString()
    if _, err := arn.Parse(valueString); err != nil {
        return ARNUnknown(), diags // Must not return validation errors.
    }

    return ARNValue(valueString), diags
}

returns ARNUnknown if an invalid ARN is passed. The unknown result will cause the validation method:

func (v ARN) ValidateAttribute(ctx context.Context, req xattr.ValidateAttributeRequest, resp *xattr.ValidateAttributeResponse) {
    if v.IsNull() || v.IsUnknown() {
        return
    }

    if !arn.IsARN(v.ValueString()) {
        resp.Diagnostics.AddAttributeError(
            req.Path,
            "Invalid ARN Value",
            "The provided value cannot be parsed as an ARN.\n\n"+
                "Path: "+req.Path.String()+"\n"+
                "Value: "+v.ValueString(),
        )
    }
}

to never pass the first condition thus validation will not take place.

If the lines:

    if _, err := arn.Parse(valueString); err != nil {
        return ARNUnknown(), diags // Must not return validation errors.
    }

are removed from ValueFromString method, then terraform plan for the aws_bedrockagent_agent snippet provided above, shows this error instead:

Error: Invalid ARN Value
│
│   with aws_bedrockagent_agent.test,
│   on main.tf line 85, in resource "aws_bedrockagent_agent" "test":
│   85:   agent_resource_role_arn = "INVALID-ARN"
│
│ The provided value cannot be parsed as an ARN.
│
│ Path: agent_resource_role_arn
│ Value: INVALID-ARN

I don't feel competent to suggest that indeed those two lines should be gone as they might be critical to some other behavior, but the fact that the method returns unknown value for invalid ARNs and unknown values are never validated, causes the issue here.

References

No response

Would you like to implement a fix?

None

github-actions[bot] commented 1 week ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue